Python 如何使用非阻塞IO写入文件?

Python 如何使用非阻塞IO写入文件?,python,file-io,nonblocking,Python,File Io,Nonblocking,我想在Python中使用非阻塞方法写入文件。在一些谷歌搜索中,我发现该语言支持fcntl,但实现该语言的方法对我来说不是很清楚 这是代码片段(我不知道哪里出了问题): 这是对文件执行非阻塞IO操作的正确方法吗?我对此表示怀疑。另外,您能推荐Python中允许我这样做的其他模块吗?写操作由操作系统缓存,几秒钟后转储到磁盘。也就是说,他们已经“不阻塞”。您无需执行任何特殊操作。这是在UNIX中打开文件非阻塞模式的方法: fd = os.open("filename", os.O_CREAT | os

我想在Python中使用非阻塞方法写入文件。在一些谷歌搜索中,我发现该语言支持
fcntl
,但实现该语言的方法对我来说不是很清楚

这是代码片段(我不知道哪里出了问题):


这是对文件执行非阻塞IO操作的正确方法吗?我对此表示怀疑。另外,您能推荐Python中允许我这样做的其他模块吗?

写操作由操作系统缓存,几秒钟后转储到磁盘。也就是说,他们已经“不阻塞”。您无需执行任何特殊操作。

这是在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
调用确实需要几秒钟的时间。即使调用是非阻塞的(从技术上讲,它不是阻塞的,它是休眠的),调用也不是异步的


另外,在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()

可能重复的不是,我需要通过使用fcntl:)保持它的简单性,如果该文件实际上装载在网络共享上呢?当然,调用只有在收到确认后才会返回?这取决于远程文件系统和实现的语义(同步或异步)。两者都有,甚至“关闭时同步”之类的例子。如何从LineReciver或服务器工厂构建的其他此类协议中访问reactor对象?可以使用POSIX AIO或Windows IOCP对常规文件进行非阻塞写入。
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()