2016-12-17 3 views
0

Python 3.4, я пытаюсь создать сервер, используя модуль websockets (ранее я использовал обычные сокеты, но хотел сделать javascript-клиент), когда столкнулся с проблемой (потому что он ожидает async, по крайней мере, если примеры должны быть доверенными, которые я раньше не использовал). Threading просто не работает. Если я запустил следующий код, панель никогда не будет напечатана, тогда как если бы я прокомментировал строку с номером yield from, она работает так, как ожидалось. Таким образом, доходность, вероятно, делает то, что я не совсем понимаю, но почему это никогда не выполняется? Должен ли я установить python 3.5?Ничья Python никогда не запускается, если run() содержит выход из

import threading 

class SampleThread(threading.Thread): 
    def __init__(self): 
     super(SampleThread, self).__init__() 
     print("foo") 

    def run(self): 
     print("bar") 
     yield from var2 

thread = SampleThread() 
thread.start() 
+0

вы не можете использовать 'yield' из подпрограммы запуска, которая должна зацикливаться навсегда/что-то делать, а не возвращать/давать что-то. –

+0

мой главный вопрос был, почему? Но похоже, что ответ кроется в том, что выход автоматически превращает всю функцию в создателя генератора, если можно так выразиться. Но как я могу использовать asyncio вместе с threading, или это глупо это делать? У меня изначально был поток для каждого клиента, чтобы узнать, есть ли у них что-нибудь, чтобы получить, но могу ли я просто превратить их в обычные объекты, если я использую async? – fdagpigj

+0

Да, это глупость в 99% случаях. Обычно программа async должна иметь одиночный цикл событий в основном потоке + пуле потоков, доступном для 'loop.run_in_executor()'. Но если вам это действительно нужно - запустите новый цикл событий в вашем потоке. –

ответ

0

Неправильный способ обработки многопоточности. run не является ни генератором, ни сопрограммой. Следует отметить, что цикл событий asyncio определен только для основного потока. Любой звонок в asyncio.get_event_loop() в новой ветке (без предварительной установки с asyncio.set_event_loop() будет исключение.

Прежде чем приступать к запуску цикла событий в новом потоке, сначала необходимо проанализировать, действительно ли вам нужен цикл событий в своем потоке. У него есть встроенный исполнитель пула потоков: loop.run_in_executor(). Это займет пул от concurrent.futures (либо ThreadPoolExecutor, либо ProcessPoolExecutor), и обеспечивает неблокирующий способ запуска процессов и потоков непосредственно из объекта цикла . Как таковые, это могут быть await -ed (с синтаксисом Python3.5)

Это означает, что если вы хотите запустить цикл событий из другого потока, вы можете сделать это thu stly:

импорт asyncio

class LoopThread(threading.Thread): 
    def __init__(self): 
     self.loop = asyncio.new_event_loop() 

    def run(): 
     ayncio.set_event_loop(self.loop) 
     self.loop.run_forever() 

    def stop(): 
     self.loop.call_soon_threadsafe(self.loop.stop) 

Отсюда, вам все еще нужно устройство потокобезопасного способ создания задач и т.д. Некоторые из кода в этом потоке можно использовать, хотя я и не имею много успеха с ним: python asyncio, how to create and cancel tasks from another thread