Есть ли простой способ асинхронной записи в файл в Python?
Я знаю, что файл io, который поставляется с Python блокирует; что нормально в большинстве случаев. В этом конкретном случае мне нужны записи, чтобы вообще не блокировать приложение или, по крайней мере, как можно меньше.






Twisted имеет неблокирующая запись в файловые дескрипторы. Если вы пишете асинхронный код, я все равно ожидаю, что вы будете использовать twisted. :)
Насколько я понимаю, асинхронный ввод-вывод - это не совсем то же самое, что неблокирующий ввод-вывод.
В случае неблокирующего ввода-вывода, как только дескриптор файла настроен на «неблокирующий», системный вызов read() (например) вернет EWOULDBLOCK (или EAGAIN), если операция чтения заблокирует вызывающий процесс в чтобы завершить операцию. Системные вызовы select(), poll(), epoll() и т. д. Предусмотрены для того, чтобы процесс мог запрашивать уведомление ОС, когда один или несколько файловых дескрипторов становятся доступный для выполнения некоторой операции ввода-вывода.
Асинхронный ввод-вывод работает путем постановки в очередь запроса ввода-вывода к файловому дескриптору, отслеживаемого независимо от вызывающего процесса. Для файлового дескриптора, который поддерживает асинхронный ввод-вывод (как правило, необработанные дисковые устройства), процесс может вызвать aio_read() (например), чтобы запросить чтение некоторого количества байтов из файлового дескриптора. Системный вызов возвращается немедленно, независимо от того, завершился ввод-вывод. Некоторое время спустя процесс затем опрашивает операционную систему на предмет завершение ввода-вывода (то есть буфер заполняется данными).
Процесс (однопоточный), который выполняет только неблокирующий ввод-вывод, сможет читать или писать из одного файлового дескриптора, готового для ввода-вывода, когда другой не готов. Но процесс должен по-прежнему синхронно выполнять системные вызовы для выполнения ввода-вывода для всех готовых файловых дескрипторов. В то время как в случае асинхронного ввода-вывода процесс просто проверяет завершение ввода-вывода (буфер заполнен данными). При асинхронном вводе-выводе ОС может работать параллельно в максимально возможной степени для обслуживания ввода-вывода, если она того пожелает.
При этом есть ли какие-нибудь оболочки для системных вызовов POSIX aio_read / write и т. д. Для Python?
Следует добавить: как говорит комментатор в первом ответе, на самом деле никакие системы не следуют O_NONBLOCK для файлов - это действительно только для сокетов. Если вам нужен переносимый ввод-вывод асинхронных файлов в Unix, вы должны использовать POSIX AIO или выгружать синхронный ввод-вывод в пул потоков.
Python 3, похоже, обладает такой функциональностью. См. PEP 3116.
Похоже, что PEP 3116 связан с новой абстракцией ввода-вывода, которая включает неблокирующий ввод-вывод. Однако неблокирующий ввод-вывод - это не то же самое, что асинхронный ввод-вывод. Неблокирующий ввод-вывод обычно не применяется к записи в локальную файловую систему.
Я разрабатываю ставки aio.h для python: пьяо
Работает только на Linux ..
Вы можете попробовать использовать Thread:
from threading import Thread
for file in list_file:
tr = Thread(target=file.write, args=(data,))
tr.start()
Это более или менее псевдокод, но я надеюсь, что вы уловили идею. Имейте в виду, что темы здесь остаются открытыми.
По моему опыту, это сработало хорошо, хотя интерпретатор продолжает работать некоторое время, пока основной скрипт завершен (необходимо использовать join()), поэтому прирост скорости настолько велик, чем кажется.
К сожалению, O_NONBLOCK (что действительно делает API fdesc, на который вы ссылаетесь) не работает с файлами локального жесткого диска. то есть в спецификации POSIX сказано, что его следует игнорировать, и он покорно игнорируется во всех известных мне UNIX-системах. Если вы думаете, что это глупая идея, я не могу согласиться с этим, но есть много исторических причин и причин реализации, почему это так. Короче говоря, если вам нужен асинхронный ввод-вывод для файлов локального жесткого диска, вам лучше использовать потоки и отложить ввод-вывод для потока ввода-вывода или использовать AIO API.