fcntl.md
1> **Источник:** https://python-all.ru/3.5/library/fcntl.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 35.9. [`fcntl`](https://python-all.ru/3.5/library/fcntl.html#module-fcntl) – Системные вызовы `fcntl` и `ioctl`89---1011Этот модуль выполняет управление файлами и вводом-выводом для файловых дескрипторов. Он является интерфейсом к системным вызовам Unix `fcntl()` и `ioctl()`. За полным описанием этих вызовов обращайтесь к страницам руководства Unix *fcntl(2)* и *ioctl(2)*.1213Все функции в этом модуле первым аргументом принимают файловый дескриптор *fd*. Это может быть целочисленный файловый дескриптор, например, возвращаемый `sys.stdin.fileno()`, или объект [`io.IOBase`](https://python-all.ru/3.5/library/io.html#io.IOBase), такой как сам `sys.stdin`, который предоставляет [`fileno()`](https://python-all.ru/3.5/library/io.html#io.IOBase.fileno), возвращающий настоящий файловый дескриптор.1415Изменено в версии 3.3: Ранее операции в этом модуле вызывали [`IOError`](https://python-all.ru/3.5/library/exceptions.html#IOError), теперь они вызывают [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).1617Модуль определяет следующие функции:1819#### `fcntl.fcntl(fd, cmd, arg=0)`2021Выполняет операцию *cmd* над файловым дескриптором *fd* (файловые объекты, предоставляющие метод [`fileno()`](https://python-all.ru/3.5/library/io.html#io.IOBase.fileno), также принимаются). Значения, используемые для *cmd*, зависят от операционной системы и доступны в виде констант в модуле [`fcntl`](https://python-all.ru/3.5/library/fcntl.html#module-fcntl), с теми же именами, что и в соответствующих C заголовочных файлах. Аргумент *arg* может быть целым числом или объектом [`bytes`](https://python-all.ru/3.5/library/functions.html#bytes). При целочисленном значении возвращаемое значение этой функции является целым значением, возвращённым вызовом C `fcntl()`. Когда аргумент – байты, он представляет двоичную структуру, например, созданную [`struct.pack()`](https://python-all.ru/3.5/library/struct.html#struct.pack). Двоичные данные копируются в буфер, адрес которого передаётся вызову C `fcntl()`. Возвращаемое значение после успешного вызова – содержимое буфера, преобразованное в объект [`bytes`](https://python-all.ru/3.5/library/functions.html#bytes). Длина возвращаемого объекта будет совпадать с длиной аргумента *arg*. Это ограничено 1024 байтами. Если информация, возвращённая в буфер операционной системой, превышает 1024 байта, это, скорее всего, приведёт к нарушению сегментации или более тонкому повреждению данных.2223Если `fcntl()` завершается неудачей, возбуждается [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).2425#### `fcntl.ioctl(fd, request, arg=0, mutate_flag=True)`2627Эта функция идентична [`fcntl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.fcntl), за исключением того, что обработка аргументов ещё более сложная.2829Параметр *request* ограничен значениями, которые могут поместиться в 32 бита. Дополнительные константы, которые могут быть полезны в качестве аргумента *request*, можно найти в модуле [`termios`](https://python-all.ru/3.5/library/termios.html#module-termios), под теми же именами, что и в соответствующих заголовочных файлах C.3031Параметр *arg* может быть целым числом, объектом, поддерживающим интерфейс буфера только для чтения (например, [`bytes`](https://python-all.ru/3.5/library/functions.html#bytes)), или объектом, поддерживающим интерфейс буфера для чтения и записи (например, [`bytearray`](https://python-all.ru/3.5/library/functions.html#bytearray)).3233Во всех случаях, кроме последнего, поведение соответствует функции [`fcntl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.fcntl) .3435Если передан изменяемый буфер, то поведение определяется значением параметра *mutate\_flag*.3637Если он ложен, изменяемость буфера игнорируется, и поведение соответствует буферу только для чтения, за исключением того, что упомянутое ограничение в 1024 байта не применяется – при условии, что передаваемый буфер имеет длину не меньше той, что операционная система хочет туда записать, всё должно работать.3839Если *mutate\_flag* истинен (по умолчанию), то буфер (фактически) передаётся базовому системному вызову [`ioctl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.ioctl), его код возврата возвращается в вызывающий Python, а новое содержимое буфера отражает действие [`ioctl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.ioctl). Это небольшое упрощение, поскольку если переданный буфер короче 1024 байт, он сначала копируется в статический буфер длиной 1024 байта, который затем передаётся [`ioctl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.ioctl) и копируется обратно в исходный буфер.4041Если `ioctl()` завершается неудачей, возбуждается исключение [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).4243Пример:4445```python46>>> import array, fcntl, struct, termios, os47>>> os.getpgrp()481334149>>> struct.unpack('h', fcntl.ioctl(0, termios.TIOCGPGRP, " "))[0]501334151>>> buf = array.array('h', [0])52>>> fcntl.ioctl(0, termios.TIOCGPGRP, buf, 1)53054>>> buf55array('h', [13341])56```5758#### `fcntl.flock(fd, operation)`5960Выполняет операцию блокировки *operation* для файлового дескриптора *fd* (также принимаются файловые объекты, предоставляющие метод [`fileno()`](https://python-all.ru/3.5/library/io.html#io.IOBase.fileno)). Подробнее см. в руководстве Unix *flock(2)*. (В некоторых системах эта функция эмулируется с помощью `fcntl()`.)6162Если `flock()` завершается неудачей, возбуждается исключение [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).6364#### `fcntl.lockf(fd, cmd, len=0, start=0, whence=0)`6566По сути, это обёртка вокруг вызовов блокировки [`fcntl()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.fcntl). *fd* – файловый дескриптор файла для блокировки или разблокировки, а *cmd* – одно из следующих значений:6768- `LOCK_UN` – разблокировка69- `LOCK_SH` – получение разделяемой блокировки70- `LOCK_EX` – получение исключительной блокировки7172Когда *cmd* равен `LOCK_SH` или `LOCK_EX`, его можно также объединить поразрядным ИЛИ с `LOCK_NB`, чтобы избежать блокировки при захвате блокировки. Если используется `LOCK_NB` и блокировку получить не удаётся, возбуждается [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError), и у исключения будет атрибут *errno*, установленный в `EACCES` или `EAGAIN` (в зависимости от операционной системы; для переносимости проверяйте оба значения). По крайней мере в некоторых системах `LOCK_EX` можно использовать только если файловый дескриптор ссылается на файл, открытый для записи.7374*len* – количество байтов для блокировки, *start* – смещение в байтах, с которого начинается блокировка, относительно *whence*, а *whence* работает как в [`io.IOBase.seek()`](https://python-all.ru/3.5/library/io.html#io.IOBase.seek), а именно:7576- `0` – относительно начала файла ([`os.SEEK_SET`](https://python-all.ru/3.5/library/os.html#os.SEEK_SET))77- `1` – относительно текущей позиции буфера ([`os.SEEK_CUR`](https://python-all.ru/3.5/library/os.html#os.SEEK_CUR))78- `2` – относительно конца файла ([`os.SEEK_END`](https://python-all.ru/3.5/library/os.html#os.SEEK_END))7980Значение по умолчанию для *start* – 0, то есть начало от начала файла. Значение по умолчанию для *len* – 0, то есть блокировка до конца файла. Значение по умолчанию для *whence* – также 0.8182Примеры (все на системе, совместимой с SVR4):8384```python85import struct, fcntl, os8687f = open(...)88rv = fcntl.fcntl(f, fcntl.F_SETFL, os.O_NDELAY)8990lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)91rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata)92```9394Обратите внимание, что в первом примере переменная возвращаемого значения *rv* будет содержать целое число; во втором примере она будет содержать объект [`bytes`](https://python-all.ru/3.5/library/functions.html#bytes). Разметка структуры для переменной *lockdata* зависит от системы, поэтому использование вызова [`flock()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.flock) может быть предпочтительнее.9596> **См. также**97>98> **Модуль [`os`](https://python-all.ru/3.5/library/os.html#module-os)**99>100> Если флаги блокировки101>102> [`O_SHLOCK`](https://python-all.ru/3.5/library/os.html#os.O_SHLOCK)103>104> и105>106> [`O_EXLOCK`](https://python-all.ru/3.5/library/os.html#os.O_EXLOCK)107>108> присутствуют в модуле109>110> [`os`](https://python-all.ru/3.5/library/os.html#module-os)111>112> (только в BSD), функция113>114> [`os.open()`](https://python-all.ru/3.5/library/os.html#os.open)115>116> предоставляет альтернативу функциям117>118> [`lockf()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.lockf)119>120> и121>122> [`flock()`](https://python-all.ru/3.5/library/fcntl.html#fcntl.flock)123>124> .125