канал (побитовое ИЛИ) при вызове fcntl.lockf()

Этот ответ содержит следующую строку:

fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)

Канал в Python представляет собой побитовое ИЛИ

Я проверил документы Python для fcntl.lockf(fd, cmd, len =0, start=0, откуда=0) и говорит, что cmd является одним из:

LOCK_UN — разблокировать

LOCK_SH — получить общую блокировку

LOCK_EX — получить эксклюзивную блокировку

Также читал об этих переменных здесь

Кто-нибудь понимает эту строку и что она делает, и будет ли она работать только с одним аргументом и без символа вертикальной черты?

LOCK_NB даже не упоминается в документах Python.


person cardamom    schedule 23.01.2019    source источник
comment
связанные с stackoverflow.com/questions/44115670/combine-bitflags, и любой другой вопрос о SO, касающийся объединения бит флаги   -  person DeepSpace    schedule 23.01.2019


Ответы (1)


Эти имена являются числовыми константами, каждая из которых является степенью двойки. Это означает, что они являются целыми числами с одноразрядным набором.

Вы можете комбинировать такие числа с |, чтобы получить целое число с несколькими наборами битов, каждый бит представляет конкретную опцию:

>>> import fcntl
>>> fcntl.LOCK_SH  # bit 1 set
1
>>> fcntl.LOCK_EX  # bit 2 set
2
>>> fcntl.LOCK_NB  # bit 3 set
4
>>> fcntl.LOCK_UN  # bit 4 set
8
>>> fcntl.LOCK_SH | fcntl.LOCK_UN  # combine bits 1 and 4
9
>>> format(fcntl.LOCK_SH | fcntl.LOCK_UN, '04b')
'1001'

Это очень распространенный способ передачи конфигурации настроек в системных вызовах. fctnl.lock() является одним из таких примеров, но есть и другие, где применяется тот же метод. Другой пример – вызов os.open(), как и re флаги модуля.

Важно понимать, что это просто целые числа. Вместо того, чтобы устанавливать флаги с помощью fcntl.LOCK_EX | fcntl.LOCK_NB (устанавливая биты 2 и 3), вы можете просто передать 6:

fcntl.lockf(fp, 6)

и не было бы никакой разницы, что касается функции lockf(). Смысл использования именованных констант в том, что их использование создает самодокументирующийся код.

person Martijn Pieters    schedule 23.01.2019
comment
Спасибо понятия не имел. Проверено в интерпретаторе, fcntl.LOCK_EX равно 2, fcntl.LOCK_NB равно 4, fcntl.LOCK_SH равно 1 и (fcntl.LOCK_EX | fcntl.LOCK_NB) равно 6. Не могли бы вы описать, какой эффект произведет изменение вещей в этой строке? например, что, если бы у вас было только fcntl.LOCK_EX и не было трубы и второй части? - person cardamom; 23.01.2019
comment
@cardamom: во-первых, вызову fcntl.lock() все равно, как вы создаете значение; вы можете передать 4 или 6. Вам нужно прочитать документацию, чтобы увидеть, что произойдет. Неиспользование LOCK_NB означает, что вызов блокируется, он не вернется, пока не будет установлена ​​блокировка. Если вы установите этот флаг, вызов вызовет исключение OSError, если блокировка не может быть установлена. - person Martijn Pieters; 23.01.2019