当 运行 和 manage.py 时 ThreadPoolExecutor 失败

ThreadPoolExecutor fails when run with manage.py

# test.py
# python 3.4.5

import time
from concurrent.futures import ThreadPoolExecutor

def a():
    time.sleep(1)
    print("success")

executor = ThreadPoolExecutor(1)
executor.submit(a).result()

上面的代码片段在 运行 喜欢

时有效
$ python test.py 
success

但是当 运行 喜欢

时失败
$ python manage.py shell < test.py 
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/var/www/cgi-bin/tracking/lib64/python3.4/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/var/www/cgi-bin/tracking/lib64/python3.4/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/www/cgi-bin/tracking/lib64/python3.4/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/www/cgi-bin/tracking/lib64/python3.4/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/var/www/cgi-bin/tracking/lib64/python3.4/site-packages/django/core/management/commands/shell.py", line 101, in handle
    exec(sys.stdin.read())
  File "<string>", line 11, in <module>
  File "/usr/lib64/python3.4/concurrent/futures/_base.py", line 395, in result
    return self.__get_result()
  File "/usr/lib64/python3.4/concurrent/futures/_base.py", line 354, in __get_result
    raise self._exception
  File "/usr/lib64/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)
  File "<string>", line 7, in a
NameError: name 'time' is not defined

这对我来说真的很奇怪。 运行使用 manage.py shell 命令导致 time 模块在函数 a 中未定义的脚本是什么?

我认为它不起作用,因为您没有将环境变量 DJANGO_SETTING_MODULE 设置为您的设置,并调用 django.setup() 或将路径设置为 sys.path.append('path/' )
(不确定)

但这 2 个选项可以起到很好的作用:

要么在函数中导入模块time

from concurrent.futures import ThreadPoolExecutor

def a():
    import time
    time.sleep(1)
    print("success")

executor = ThreadPoolExecutor(1)
executor.submit(a).result()

或像您一样在开头 import time,并将该模块用作 global 模块:

from concurrent.futures import ThreadPoolExecutor
import time

def a():
    global time
    time.sleep(1)
    print("success")

executor = ThreadPoolExecutor(1)
executor.submit(a).result()

检查 Django 实现(django/core/management/commands/shell.py 第 83 行):

# Execute stdin if it has anything to read and exit.
# Not supported on Windows due to select.select() limitations.
if sys.platform != 'win32' and select.select([sys.stdin], [], [], 0)[0]:
    exec(sys.stdin.read())
    return

开发人员没有在exec()方法中添加globals()作用域,这意味着您在handle()作用域的'locals()'字典中导入时间和ThreadPoolExecutor (在 shell.py 中)但是之后,当您尝试在 a() 内部使用时,它会尝试在 "a" 范围的 locals() 字典和 globals() 中搜索字典所以它会抛出一个导入错误,你可以在这个片段中看到一个例子:

command = """
import time
def b():
    time.sleep(1)
b()
"""
def a():
    exec(command)
a()

并尝试将 exec(command) 更改为 exec(command, globals())