为什么将io.BytesIO流作为参数传递时关闭?

eri*_*cso 5 python django stream

我有一个Django应用,用户在其中发布文件。视图将获取文件,将其传递给线程函数并进行处理。问题是,有时io.BytesIO流在无法读取之前就被关闭了,我无法弄清为什么关闭了它。

我正在使用Xlrd库处理Excel文件。对于某些上载的Excel文件,流保持打开状态,而另一些保持关闭。我不知道到底是怎么回事找出原因。我要的是调试建议。我无法提供完整的代码,但下面概述了代码路径。

我的Django视图从POST请求中获取文件:

ufile = request.FILES['upload-file'].file
Run Code Online (Sandbox Code Playgroud)

ufile是的实例io.BytesIO。我有一个将流复制到命名临时文件的功能

@contextmanager
def temp_input_file(file_):
  temp = tempfile.NamedTemporaryFile(delete=False)
  shutil.copyfileobj(file_, temp)
  temp.close()
  yield temp.name
  os.unlink(temp.name)
Run Code Online (Sandbox Code Playgroud)

此contextmanager装饰的功能稍后使用。下一步是创建一个线程来处理上传的文件:

  job.run_job(
    method=process_excel_file,
    uploaded_file=ufile
  )
Run Code Online (Sandbox Code Playgroud)

我正在做的是传递一个函数process_excel_file和上载的“文件”,但实际上是io.BytesIO流到job.run_job,它创建了一个线程

def run_job(self, method, **kwargs):
  thread = threading.Thread()
  thread.run = lambda : method(
    job_id=self.job_db_record.id,
    **kwargs
  )
  thread.start()
Run Code Online (Sandbox Code Playgroud)

因此process_excel_file被传递到method变量中,而ufile在中kwargs。在线程中运行的函数process_excel_file如下所示:

def process_excel_file(ufile):
  with temp_input_file(ufile) as temp_file:
    in_book = xlrd.open_workbook(temp_file)
    ... # do stuff with in_book
Run Code Online (Sandbox Code Playgroud)

因此,发生什么事情是当我使用temp_input_file上下文管理器功能时,ValueError由于流关闭而引发了异常。相反,如果我重构代码以在视图中创建临时文件并传递临时文件名而不是类似文件的对象,则它起作用,因为流在​​传递到后在某处关闭job.run_job。有什么想法为什么会关闭流?更麻烦的是,某些文件不会关闭流。