pythonpython-3.xflockfcntllockfile

pipe ("bitwise OR") in call to fcntl.lockf()


This answer contains the following line:

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

The pipe, is in Python a "bitwise OR"

I have checked the Python docs for fcntl.lockf(fd, cmd, len=0, start=0, whence=0) and it says that cmd is one of:

LOCK_UN – unlock

LOCK_SH – acquire a shared lock

LOCK_EX – acquire an exclusive lock

Have also been reading about those variables here

Does anyone understand that line and what it does and if it would work with just one argument and no pipe symbol?

LOCK_NB is not even mentioned in the Python docs..


Solution

  • Those names are numeric constants, each a power of 2. That means they are integers with a single bit set.

    You can combine such numbers with | to produce an integer with multiple bits set, each bit representing a specific option:

    >>> 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'
    

    This is a very common way of passing setting configuration in system calls. fctnl.lock() is one such example, but there are many more where the same technique applies. The os.open() call is another example, as are the re module flags.

    It is important to realise that these are just integers. Instead of setting the flags with fcntl.LOCK_EX | fcntl.LOCK_NB (setting bits 2 and 3), you could just pass in 6:

    fcntl.lockf(fp, 6)
    

    and there would be no difference, as far as the lockf() function is concerned. The point of using named constants is that using these makes for self-documenting code.