@kiril443

Как поделиться переменными между потоками из разных модулей?

В основной модуль импортируется функция из другого модуля
Запускается поток с этой функцией, которая должна менять значения переменной из основного модуля

1) Как расшарить переменные на другой модуль?
2) Правильно понимаю что поток независимо от места вызова(main.py) всегда будет использовать набор переменных из модуля где находится target (extra_thread.py)?

main.py
import threading
import time

from extra_thread import f  # импортируем функцию из другого файла для потока

v = 1

threading.Thread(target=f).start()  # функция меняет значение v

time.sleep(0.3)
print(v)  # в итоге значение v = 1


extra_thread.py
def f():
    global v
    v = 555
  • Вопрос задан
  • 850 просмотров
Пригласить эксперта
Ответы на вопрос 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
Не используйте глобальные переменные. Не используйте глобальные переменные в конкурентной среде ещё сильнее.
Ответ написан
Комментировать
Vindicar
@Vindicar
RTFM!
Для начала скажи, какую задачу ты пытаешься решить.
Для случая с одноразовым потоком-воркером, тебе не нужна глобальная переменная. Достаточно класса.
import threading

class MyWorkerThread(threading.Thread):
    def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
        # поток не должен их менять!
        super().__init__()
        self.arg1 = arg1
        self.arg2 = arg2
        self.result: t.Optional[float] = None
    def run(self):
        time.sleep(10) # имитируем длительную работу
        self.result = self.arg1 + self.arg2

И тогда ты можешь его использовать так:
worker = MyWorkerThread(42, 69)
worker.start()
while True: 
    if worker.is_alive():  # проверяем, жив ли поток
        # делаешь ещё что-то, пока поток работает
        print('Still working...')
        time.sleep(0.5)
    else:
        # поток завершился, даём знать пользователю.
        print(f'Done! Result is {worker.result}!')
        break # выходим из цикла

Если же тебе нужно просто дождаться конца потока, ничего не делая в процессе, можно сделать просто worker.join()

Сложности начинаются, когда тебе нужно взаимодействовать с длительным потоком. Усложним пример:
import threading, queue

class MyWorkerThread(threading.Thread):
    def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
        # поток не должен их менять!
        super().__init__()
        self.arg1 = arg1
        self.arg2 = arg2
        self.result: t.Optional[float] = None
        self.progress = queue.Queue()
    def run(self):
        for i in range(10):
            time.sleep(1) # имитируем длительную работу
            self.progress.put(i/10) # сообщаем о прогрессе
        self.result = self.arg1 + self.arg2
        self.progress.put(1.00)

Тогда код использования изменится следующим образом:
worker = MyWorkerThread(42, 69)
worker.start()
while True: 
    if worker.is_alive():  # проверяем, жив ли поток
        # делаешь ещё что-то, пока поток работает
        try:
            progress = worker.progress.get(block=True, timeout=0.5)
        except queue.Empty: # поток ничего не сообщил
            print('Still working...')
        else:
            print(f'Still working... {progress:.0%}')
            worker.progress.task_done() # один вызов task_done() на один успешный вызов get()!
    else:
        # поток завершился, даём знать пользователю.
        print(f'Done! Result is {worker.result}!')
        break # выходим из цикла

Если тебе нужно передать потоку новые задания, то можешь использовать ещё одну queue.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы