<p dir="auto">As <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="256206011" data-permission-text="Title is private" data-url="https://github.com/pallets/flask/issues/2468" data-hovercard-type="issue" data-hovercard-url="/pallets/flask/issues/2468/hovercard" href="https://github.com/pallets/flask/issues/2468">#2468</a> has mentioned, send_file opens a file that mean to be closed by some further processing of the WSGI server. However, test_client does not really run the WSGI server, causing the opened file not closed until all test ends, and thus triggers a ResourceWarning and causes cleaning code after a test request to fail.</p>
<h1 dir="auto">Expected Behavior</h1>
<p dir="auto">A file opened by send_file() should be closed after response is sent.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from flask import Flask
from flask import send_file
import unittest
import os

app = Flask(__name__, root_path='.')

@app.route('/&lt;path:filepath&gt;')
def handle_request(filepath):
    return send_file(filepath)

class Test(unittest.TestCase):
    def test(self):
        temp_file = os.path.join(os.path.dirname(__file__), 'test.txt')
        for i in ('123abc', '&amp;@!#^*', '你好嗎'):
            with self.subTest(i=i):
                test_text = 'test' + str(i)
                with open(temp_file, 'w', encoding='UTF-8') as f:
                    f.write(test_text)
                try:
                    with app.test_client() as c:
                        r = c.get(temp_file)
                        self.assertEqual(r.data.decode('UTF-8'), test_text)
                finally:
                    os.remove(temp_file)

if __name__ == '__main__':
    unittest.main()"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">flask</span> <span class="pl-k">import</span> <span class="pl-v">Flask</span>
<span class="pl-k">from</span> <span class="pl-s1">flask</span> <span class="pl-k">import</span> <span class="pl-s1">send_file</span>
<span class="pl-k">import</span> <span class="pl-s1">unittest</span>
<span class="pl-k">import</span> <span class="pl-s1">os</span>

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">Flask</span>(<span class="pl-s1">__name__</span>, <span class="pl-s1">root_path</span><span class="pl-c1">=</span><span class="pl-s">'.'</span>)

<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">route</span>(<span class="pl-s">'/&lt;path:filepath&gt;'</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">handle_request</span>(<span class="pl-s1">filepath</span>):
    <span class="pl-k">return</span> <span class="pl-en">send_file</span>(<span class="pl-s1">filepath</span>)

<span class="pl-k">class</span> <span class="pl-v">Test</span>(<span class="pl-s1">unittest</span>.<span class="pl-v">TestCase</span>):
    <span class="pl-k">def</span> <span class="pl-en">test</span>(<span class="pl-s1">self</span>):
        <span class="pl-s1">temp_file</span> <span class="pl-c1">=</span> <span class="pl-s1">os</span>.<span class="pl-s1">path</span>.<span class="pl-en">join</span>(<span class="pl-s1">os</span>.<span class="pl-s1">path</span>.<span class="pl-en">dirname</span>(<span class="pl-s1">__file__</span>), <span class="pl-s">'test.txt'</span>)
        <span class="pl-k">for</span> <span class="pl-s1">i</span> <span class="pl-c1">in</span> (<span class="pl-s">'123abc'</span>, <span class="pl-s">'&amp;@!#^*'</span>, <span class="pl-s">'你好嗎'</span>):
            <span class="pl-k">with</span> <span class="pl-s1">self</span>.<span class="pl-en">subTest</span>(<span class="pl-s1">i</span><span class="pl-c1">=</span><span class="pl-s1">i</span>):
                <span class="pl-s1">test_text</span> <span class="pl-c1">=</span> <span class="pl-s">'test'</span> <span class="pl-c1">+</span> <span class="pl-en">str</span>(<span class="pl-s1">i</span>)
                <span class="pl-k">with</span> <span class="pl-en">open</span>(<span class="pl-s1">temp_file</span>, <span class="pl-s">'w'</span>, <span class="pl-s1">encoding</span><span class="pl-c1">=</span><span class="pl-s">'UTF-8'</span>) <span class="pl-k">as</span> <span class="pl-s1">f</span>:
                    <span class="pl-s1">f</span>.<span class="pl-en">write</span>(<span class="pl-s1">test_text</span>)
                <span class="pl-k">try</span>:
                    <span class="pl-k">with</span> <span class="pl-s1">app</span>.<span class="pl-en">test_client</span>() <span class="pl-k">as</span> <span class="pl-s1">c</span>:
                        <span class="pl-s1">r</span> <span class="pl-c1">=</span> <span class="pl-s1">c</span>.<span class="pl-en">get</span>(<span class="pl-s1">temp_file</span>)
                        <span class="pl-s1">self</span>.<span class="pl-en">assertEqual</span>(<span class="pl-s1">r</span>.<span class="pl-s1">data</span>.<span class="pl-en">decode</span>(<span class="pl-s">'UTF-8'</span>), <span class="pl-s1">test_text</span>)
                <span class="pl-k">finally</span>:
                    <span class="pl-s1">os</span>.<span class="pl-en">remove</span>(<span class="pl-s1">temp_file</span>)

<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">'__main__'</span>:
    <span class="pl-s1">unittest</span>.<span class="pl-en">main</span>()</pre></div>
<h3 dir="auto">Actual Behavior</h3>
<p dir="auto">The opened file is not closed properly after the response is sent, causing following code in the test fail to delete the file (which is temporarily generated for testing purpose).</p>
<div class="highlight highlight-text-python-traceback notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="......\test.py:22: ResourceWarning: unclosed file &lt;_io.BufferedReader name='......\\test.txt'&gt;
  r = c.get(temp_file)
ResourceWarning: Enable tracemalloc to get the object allocation traceback
......\case.py:704: ResourceWarning: unclosed file &lt;_io.BufferedReader name='......\\test.txt'&gt;
  outcome.errors.clear()
ResourceWarning: Enable tracemalloc to get the object allocation traceback

======================================================================
ERROR: test (__main__.Test) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &quot;......\test.py&quot;, line 25, in test
    os.remove(temp_file)
PermissionError: [WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'

======================================================================
ERROR: test (__main__.Test) (i=2)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &quot;......\test.py&quot;, line 25, in test
    os.remove(temp_file)
PermissionError: [WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'

======================================================================
ERROR: test (__main__.Test) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &quot;......\test.py&quot;, line 25, in test
    os.remove(temp_file)
PermissionError: [WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'

----------------------------------------------------------------------
Ran 1 test in 0.010s

FAILED (errors=3)"><pre class="notranslate">......\test.py:22: ResourceWarning: unclosed file &lt;_io.BufferedReader name='......\\test.txt'&gt;
  r = c.get(temp_file)
<span class="pl-en">ResourceWarning</span>: <span class="pl-s">Enable tracemalloc to get the object allocation traceback</span>
......\case.py:704: ResourceWarning: unclosed file &lt;_io.BufferedReader name='......\\test.txt'&gt;
  outcome.errors.clear()
<span class="pl-en">ResourceWarning</span>: <span class="pl-s">Enable tracemalloc to get the object allocation traceback</span>

======================================================================
<span class="pl-en">ERROR</span>: <span class="pl-s">test (__main__.Test) (i=1)</span>
----------------------------------------------------------------------
Traceback (most recent call last):
  File <span class="pl-s">"......\test.py"</span>, line <span class="pl-c1">25</span>, in <span class="pl-en">test</span>
    os.remove(temp_file)
<span class="pl-en">PermissionError</span>: <span class="pl-s">[WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'</span>

======================================================================
<span class="pl-en">ERROR</span>: <span class="pl-s">test (__main__.Test) (i=2)</span>
----------------------------------------------------------------------
Traceback (most recent call last):
  File <span class="pl-s">"......\test.py"</span>, line <span class="pl-c1">25</span>, in <span class="pl-en">test</span>
    os.remove(temp_file)
<span class="pl-en">PermissionError</span>: <span class="pl-s">[WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'</span>

======================================================================
<span class="pl-en">ERROR</span>: <span class="pl-s">test (__main__.Test) (i=3)</span>
----------------------------------------------------------------------
Traceback (most recent call last):
  File <span class="pl-s">"......\test.py"</span>, line <span class="pl-c1">25</span>, in <span class="pl-en">test</span>
    os.remove(temp_file)
<span class="pl-en">PermissionError</span>: <span class="pl-s">[WinError 32] 程序無法存取檔案，因為檔案正由另一個程序使用。: '......\\test.txt'</span>

----------------------------------------------------------------------
Ran 1 test in 0.010s

FAILED (errors=3)</pre></div>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Python version: 3.8.1</li>
<li>Flask version: 1.1.2</li>
<li>Werkzeug version: 1.0.1</li>
</ul>
<p dir="auto">The link <a href="http://flask.pocoo.org/docs/0.12/.latex/Flask.pdf" rel="nofollow">http://flask.pocoo.org/docs/0.12/.latex/Flask.pdf</a> referenced from <a href="http://flask.pocoo.org/" rel="nofollow">http://flask.pocoo.org/</a> is broken.</p>