Подтвердить что ты не робот

Как писать в файл с помощью неблокирующего ввода-вывода?

Я хочу записать в файл, используя неблокирующий метод в Python. В некоторых поисковых системах я обнаружил, что язык поддерживает fcntl, чтобы сделать это, но метод реализации того же не очень ясен для меня.

Это фрагмент кода (я не знаю, где я ошибаюсь):

import os, fcntl
nf = fcntl.fcntl(0,fcntl.F_UNCLK)
fcntl.fcntl(0,fcntl.F_SETFL , nf | os.O_NONBLOCK )
nf = open ("test.txt", 'a') 
nf.write ( " sample text \n")

Является ли это правильным способом выполнения неблокирующей операции ввода-вывода в файле? Я сомневаюсь в этом. Кроме того, можете ли вы предложить любые другие модули на Python, которые позволяют мне это делать?

4b9b3361

Ответ 1

Вот как вы включаете неблокирующий режим для файла в UNIX:

fd = os.open("filename", os.O_CREAT | os.O_WRONLY | os.O_NONBLOCK)
os.write(fd, "data")
os.close(fd)

Однако в UNIX включение неблокирующего режима не имеет видимого эффекта для обычных файлов! Несмотря на то, что файл находится в неблокирующем режиме, вызов os.write не будет возвращаться немедленно, он будет спать до тех пор, пока запись не будет завершена. Чтобы доказать это экспериментально, попробуйте следующее:

import os
import datetime

data = "\n".join("testing\n" * 10 for x in xrange(10000000))
print("Size of data is %d bytes" % len(data))

print("open at %s" % str(datetime.datetime.now()))
fd = os.open("filename", os.O_CREAT | os.O_WRONLY | os.O_NONBLOCK)
print("write at %s" % str(datetime.datetime.now()))
os.write(fd, data)
print("close at %s" % str(datetime.datetime.now()))
os.close(fd)
print("end at %s" % str(datetime.datetime.now()))

Вы заметите, что вызов os.write занимает несколько секунд. Хотя вызов не блокируется (технически, он не блокирует, он спал), вызов не является асинхронным.


AFAIK, нет возможности писать в файл асинхронно в Linux или в Windows. Вы можете имитировать его, однако, используя потоки. Для этой цели Twisted имеет метод с именем deferToThread. Вот как вы его используете:

from twisted.internet import threads, reactor

data = "\n".join("testing\n" * 10 for x in xrange(10000000))
print("Size of data is %d bytes" % len(data))

def blocking_write():
    print("Starting blocking_write")
    f = open("testing", "w")
    f.write(data)
    f.close()
    print("End of blocking_write")

def test_callback():
    print("Running test_callback, just for kicks")

d = threads.deferToThread(blocking_code)
reactor.callWhenRunning(cc)
reactor.run()

Ответ 2

Записи кэшируются ОС и сбрасываются на диск через несколько секунд. То есть, они уже "не блокируют". Вам не нужно ничего особенного делать.