Non-blocking file read
<p>How can I read the contents of a binary or a text file in a non-blocking mode?</p>

<p>For binary files: when I <code>open(filename, mode='rb')</code>, I get an instance of <code>io.BufferedReader</code>. The documentation fort <code>io.BufferedReader.read</code> <a href="https://docs.python.org/3.5/library/io.html#io.BufferedReader.read" rel="nofollow">says</a>:</p>

<blockquote>
  <p>Read and return size bytes, or if size is not given or negative, until EOF or if the read call would block in non-blocking mode.</p>
</blockquote>

<p>Obviously a straightforward <code>open(filename, 'rb').read()</code> is in a blocking mode. To my surprise, I could not find an explanation anywhere in the <code>io</code> docs of how to choose the non-blocking mode.</p>

<p>For text files: when I <code>open(filename, mode='rt')</code>, I get <code>io.TextIOWrapper</code>. I assume the relevant docs are those for <code>read</code> in its base class, <code>io.TextIOBase</code>; and <a href="https://docs.python.org/3.5/library/io.html#io.TextIOBase.read" rel="nofollow">according to those docs</a>, there seems no way to do non-blocking read at all:</p>

<blockquote>
  <p>Read and return at most size characters from the stream as a single str. If size is negative or None, reads until EOF.</p>
</blockquote>

<p>File operations are blocking. There is no non-blocking mode.</p>

<p>But you can create a thread which reads the file in the background. In Python 3, <a href="https://docs.python.org/3.4/library/concurrent.futures.html#module-concurrent.futures" rel="nofollow"><code>concurrent.futures</code> module</a> can be useful here.</p>

<pre><code>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()
</code></pre>

<p>Or, if you need a callback to be called when the operation is done:</p>

<pre><code>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...
</code></pre>

python python-3.x io