2

Я немного экспериментирую с асинхронными протоколами python. Я нашел this example из официальных документов и хотел немного изменить его и воспроизвести его beahviour. Поэтому я написал следующие два сценария:Python asyncio простой пример

# file: get_rand.py 
from random import choice 
from time import sleep 

def main(): 
    print(choice('abcdefghijklmnopqrstuvwxyz')) 
    sleep(2) 

if __name__ == '__main__': 
    main() 

и:

# file: async_test.py 
import asyncio 

class Protocol(asyncio.SubprocessProtocol): 

    def __init__(self, exit_future): 
     self.exit_future = exit_future 
     self.output = bytearray() 
     print('Protocol initialised') 

    def pipe_data_received(self, fd, data): 
     print('Data received') 
     self.output.extend(data) 

    #def pipe_connection_lost(self, fd, exc): 
    # print('Pipe connection lost for the following reason:') 
    # print(exc) 

    def subprocess_exited(self): 
     print('Subprocess exited') 
     self.exit_future.set_result(True) 


@asyncio.coroutine 
def get_rand(loop): 
    exit_future = asyncio.Future(loop=loop) 
    print('Process created') 
    created = loop.subprocess_exec(lambda: Protocol(exit_future), 
            'python3.5', 'get_rand.py', 
            stdin=None, stderr=None) 
    print('Getting pipes...') 
    transport, protocol = yield from created 
    print('Waiting for child to exit...') 
    yield from exit_future 
    transport.close() 
    print('Gathering data...') 
    data = bytes(protocol.output) 
    print('Returning data...') 
    return data.decode('ascii').rstrip() 

def main(): 
    loop = asyncio.get_event_loop() 
    print('Event loop started') 
    data = loop.run_until_complete(get_rand(loop)) 
    print('Event loop ended') 
    print(data) 
    loop.close() 

if __name__ == '__main__': 
    main() 

Когда я бегу async_test.py я получаю следующий результат:

$ python3.5 async_test.py 
Event loop started 
Process created 
Getting pipes... 
Protocol initialised 
Waiting for child to exit... 
Data received 

И это просто висит.

Если я раскомментировать метод pipe_connection_lost, выход заключается в следующем:

$ python3.5 async_test.py 
Event loop started 
Process created 
Getting pipes... 
Protocol initialised 
Waiting for child to exit... 
Data received 
Pipe connection lost for the following reason: 
None 

и до сих пор процесс виснет. Я думаю, что по какой-то причине дочерний процесс (get_rand.py) закрывает трубу (как видно из выведенного выше), но не прерывается, так что родитель может разблокировать от yield from exit_future. Я действительно не понимаю причину такого поведения, учитывая, что мой код в основном скопирован из примера в документах python.

ответ

Смежные вопросы