ThreadPoolExecutor 在使用 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命令运行脚本会导致函数a中未定义time模块是什么?

检查 Django 实现(django/core/management/command/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(("字典(shell.py(中导入时间和 ThreadPoolExecutor,但之后,当您尝试在a()中使用时,它会尝试在"a"范围的locals()字典和globals()字典中搜索,因此它会抛出导入错误, 您可以在此代码段中看到一个示例:

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

并尝试通过exec(command, globals())来改变exec(command)

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

但是这两个选项可以像魅力一样工作:

要么在函数内部导入模块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()

最新更新