如何以非阻塞模式读取二进制文件或文本文件的内容?
对于二进制文件:当我open(filename, mode='rb')
时,我得到一个io.BufferedReader
的实例。文档堡io.BufferedReader.read
says:
读取并返回大小字节,或者如果未给出大小或为负,直到EOF或读取调用将在非阻塞模式下阻塞。
显然,直截了当的open(filename, 'rb').read()
处于阻止模式。令我惊讶的是,我无法在io
文档中的任何地方找到有关如何选择非阻塞模式的解释。
对于文本文件:当我open(filename, mode='rt')
时,我得到io.TextIOWrapper
。我假设相关文档是基类read
中io.TextIOBase
的文档。和according to those docs,根本没有办法进行非阻塞读取:
从流中读取并返回最多大小字符作为单个str。如果大小为负或无,则读取直至EOF。
答案 0 :(得分:7)
文件操作正在阻止。没有非阻塞模式。
但是你可以创建一个在后台读取文件的线程。在Python 3中,concurrent.futures
module在这里很有用。
from concurrent.futures import ThreadPoolExecutor
def read_file(filename):
with open(filename, 'rb') as f:
return f.read()
executor = concurrent.futures.ThreadPoolExecutor(1)
future_file = executor.submit(read_file, 'C:\\Temp\\mocky.py')
# continue with other work
# later:
if future_file.done():
file_contents = future_file.result()
或者,如果您需要在操作完成时调用回调:
def on_file_reading_finished(future_file):
print(future_file.result())
future_file = executor.submit(read_file, 'C:\\Temp\\mocky.py')
future_file.add_done_callback(on_file_reading_finished)
# continue with other code while the file is loading...
答案 1 :(得分:2)
我建议使用aiofile。 https://pypi.python.org/pypi/aiofiles/0.2.1
f = yield from aiofiles.open('filename', mode='r')
try:
contents = yield from f.read()
finally:
yield from f.close()
print(contents)
'My file contents'
异步样式版
async def read_without_blocking():
f = await aiofiles.open('filename', mode='r')
try:
contents = await f.read()
finally:
await f.close()
答案 2 :(得分:2)
Python 确实支持非阻塞读取,至少在 Unix 类型系统上,通过设置 O_NONBLOCK
flag。在 Python 3.5+ 中,有 os.set_blocking()
function 使这更容易:
import os
f = open(filename, 'rb')
os.set_blocking(f.fileno(), False)
f.read() # This will be non-blocking.
然而,正如 zvone's answer 所指出的,这不一定适用于实际的磁盘文件。不过,这不是 Python 的东西,而是操作系统的限制。正如 Linux open(2) man page 所述:
<块引用>注意这个标志对普通文件和块设备没有影响; 也就是说,当设备活动停止时,I/O 操作将(短暂地)阻塞 需要,无论是否设置了 O_NONBLOCK。
但它确实表明这可能会在未来实施:
<块引用>由于 O_NONBLOCK 语义可能最终会被实现, 应用程序在指定时不应依赖于阻塞行为 此标志用于常规文件和块设备。