Non-blocking file read
Python does support non-blocking reads, at least on Unix type systems, by setting the O_NONBLOCK
flag. In Python 3.5+, there is the os.set_blocking()
function which makes this easier:
import os
f = open(filename, 'rb')
os.set_blocking(f.fileno(), False)
f.read() # This will be non-blocking.
However, as zvone's answer notes, this doesn't necessarily work on actual disk files. This isn't a Python thing though, but an OS limitation. As the Linux open(2) man page states:
Note that this flag has no effect for regular files and block devices; that is, I/O operations will (briefly) block when device activity is required, regardless of whether O_NONBLOCK is set.
But it does suggest this may be implemented in the future:
Since O_NONBLOCK semantics might eventually be implemented, applications should not depend upon blocking behavior when specifying this flag for regular files and block devices.
I suggest using aiofiles - a library for handling local disk files in asyncio applications.
import aiofiles
async def read_without_blocking():
f = await aiofiles.open('filename', mode='r')
try:
contents = await f.read()
finally:
await f.close()
File operations are blocking. There is no non-blocking mode.
But you can create a thread which reads the file in the background. In Python 3, concurrent.futures
module can be useful here.
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()
Or, if you need a callback to be called when the operation is done:
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...