Ошибка ThreadPoolExecutor при запуске с manage.py - PullRequest
0 голосов
/ 11 мая 2018
# 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?

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Проверка в реализации Django (строка 83 django / core / management / commands / shell.py):

# 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

Разработчики не добавили область действия globals() в метод exec(), это означает, что вы импортируете time и ThreadPoolExecutor в словарь 'locals ()' области действия handle() (в shell.py), но после , когда вы пытаетесь использовать внутри a(), он пытается найти в словаре locals() области «a» и в словаре globals(), чтобы он выдавал ошибку импорта, вы можете увидеть пример в этом фрагменте:

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

и попробуйте изменить exec(command) на exec(command, globals())

0 голосов
/ 11 мая 2018

Я думаю, что это не работает, потому что вы не установили переменную окружения 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()
...