非阻塞文件读取

时间:2016-10-09 21:12:12

标签: python python-3.x io

如何以非阻塞模式读取二进制文件或文本文件的内容?

对于二进制文件:当我open(filename, mode='rb')时,我得到一个io.BufferedReader的实例。文档堡io.BufferedReader.read says

  

读取并返回大小字节,或者如果未给出大小或为负,直到EOF或读取调用将在非阻塞模式下阻塞。

显然,直截了当的open(filename, 'rb').read()处于阻止模式。令我惊讶的是,我无法在io文档中的任何地方找到有关如何选择非阻塞模式的解释。

对于文本文件:当我open(filename, mode='rt')时,我得到io.TextIOWrapper。我假设相关文档是基类readio.TextIOBase的文档。和according to those docs,根本没有办法进行非阻塞读取:

  

从流中读取并返回最多大小字符作为单个str。如果大小为负或无,则读取直至EOF。

3 个答案:

答案 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 语义可能最终会被实现, 应用程序在指定时不应依赖于阻塞行为 此标志用于常规文件和块设备。