Могут ли потоки python обращаться к переменным в пространстве имен?

У меня есть сценарий, который создает кучу потоков, запускает программу для использования потоков для запуска задач из очереди и возвращает что-то из каждого потока. Я хочу подсчитать, сколько из них успешно возвращено, поэтому я устанавливаю переменную «успешно = 0» и увеличиваю ее каждый раз, когда очередь сообщает о завершении задачи.

Тем не менее, я получаю «UnboundLocalError: локальная переменная« успешно », на которую ссылаются перед назначением»

Что происходит?

Вот пример кода:

successful = 0 q = Queue(200) for i in range(100): t=Thread(target=foo) t.daemon=True t.start() def foo(): while True: task=q.get() #do some work print task successful+=1 # triggers an error q.task_done() for i in range(100): q.put("Foo") q.join() print successful 

  • Количество наиболее часто встречающихся 100 слов из предложений в Dataframe Pandas
  • XMODEM для python
  • Использование Numpy для создания финансового ценового стола Yahoo
  • Что означает название «cp27» или «cp35» в Python?
  • Синхронизация потоков в Python
  • scipy.interpolate.UnivariateSpline не сглаживается независимо от параметров
  • Размещение объектов Python в общей памяти
  • Открыть браузер с селеном
  • 3 Solutions collect form web for “Могут ли потоки python обращаться к переменным в пространстве имен?”

     successful+=1 

    не является потокобезопасной. С несколькими потоками, пытающимися увеличить общую глобальную переменную, могут возникать конфликты, и successful не будет увеличиваться должным образом.

    Чтобы избежать этой ошибки, используйте блокировку:

     lock = threading.Lock() def foo(): global successful while True: ... with lock: successful+=1 

    Вот какой код, чтобы продемонстрировать, что x + = 1 не является потокобезопасным:

     import threading lock = threading.Lock() x = 0 def foo(): global x for i in xrange(1000000): # with lock: # Uncomment this to get the right answer x += 1 threads = [threading.Thread(target=foo), threading.Thread(target=foo)] for t in threads: t.daemon = True t.start() for t in threads: t.join() print(x) 

    выходы:

     % test.py 1539065 % test.py 1436487 

    Эти результаты не согласуются и меньше ожидаемого 2000000. Раскомментирование блокировки дает правильный результат.

    Проблема возникает из-за того, что переменная, назначенная внутри функции, считается локальной для этой функции. Если вы хотите изменить значение переменной successfull , созданное вне foo , вам нужно явно сообщить интерпретатору, что вы собираетесь работать с глобальной переменной внутри функции. Это можно сделать следующим образом:

     def foo(): global successfull while True: task=q.get() #do some work print task successful+=1 # triggers an error q.task_done() 

    Теперь код должен работать должным образом.

    Исходя из ошибки области переменной Python ,

    Я должен был поставить «глобальный успех» под «def foo ():».

    К сожалению.

    Python - лучший язык программирования в мире.