web-dev-qa-db-ja.com

ノンブロッキングIOを使用してファイルに書き込む方法は?

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")

これは、ファイルに対して非ブロッキングIO操作を実行する正しい方法ですか?私はそれを疑っています。また、Pythonで他のモジュールを提案できますか?許可しますか?

15
Rahul

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呼び出しには数秒かかります。呼び出しは非ブロッキング(技術的にはブロッキングではなく、スリープ中)ですが、呼び出しはnot非同期です。


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()
17
Flimm

書き込みはOSによってキャッシュされ、数秒後にディスクにダンプされます。つまり、それらはすでに「ブロックされていません」。特別なことをする必要はありません。

4
jcea