Все асинхронные работники ушли. Когда asyncio.run не возвращается?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Все асинхронные работники ушли. Когда asyncio.run не возвращается?

Сообщение Anonymous »

Кто-нибудь знает, почему этот asyncio.run не завершается в этой программе при завершении дочернего процесса?
Я запускаю программу ниже, а затем pkill ssh, чтобы завершить процесс ssh.
AFAICT все асинхронные работники:
  • runcommand
  • read_from_process
  • write_to_process
    все ушли. Программа печатает:
finally... worker 1 done
finally... worker 2 done
t1, t2 done
finally
finally .. DONE returncode=255

Но «ALL DONE» не выводится до тех пор, пока не будет напечатан возврат (и ps не подтвердит, что процесс Python не завершился).
import asyncio
import os
import pty
import sys
import termios
import traceback
import tty

async def run_command(command):
# Create a pseudoterminal pair (master and slave)
master_fd, slave_fd = pty.openpty()
old_tty = termios.tcgetattr(sys.stdin)

try:
# Set the terminal in raw mode for capturing control characters
tty.setraw(sys.stdin.fileno())
# Start the process using the slave as stdin, stdout, stderr
process = await asyncio.create_subprocess_exec(
*command,
stdin=slave_fd,
stdout=slave_fd,
stderr=slave_fd
)

# Close the slave in the parent process
os.close(slave_fd)

# Start tasks to handle reading from and writing to the terminal
async def onCancel(coro, proc):
try:
await coro
except asyncio.CancelledError as e:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
except OSError as e:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
# Cancel other end.
if proc == 1:
t2.cancel()
else:
t1.cancel()
# process.kill()

# print("".join(traceback.format_exception(type(e), e, e.__traceback__)), file=sys.stderr)
# cancel_task(t1)
# cancel_task(t2)
# print("".join(traceback.format_exception(type(e), e, e.__traceback__)), file=sys.stderr)
except Exception as e:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
print("".join(traceback.format_exception(type(e), e, e.__traceback__)), file=sys.stderr)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
print(f"finally... worker {proc} done")
# cancel_task(t1)
# cancel_task(t2)

t1 = asyncio.create_task(onCancel(read_from_process(master_fd), 1))
t2 = asyncio.create_task(onCancel(write_to_process(master_fd), 2))

await asyncio.gather(t1, t2)
print("t1, t2 done")
await process.wait()

# asyncUtil.printWorkers() # Shows only run_command coro remains

finally:
print("finally")
# Restore the terminal to its previous state
os.close(master_fd)
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
print(f"finally .. DONE returncode={process.returncode}")

async def read_from_process(master_fd):
"""Asynchronously read from the master side of the PTY and print to stdout. Note that stdin/stdout are combined."""
loop = asyncio.get_event_loop()
while True:
data = await loop.run_in_executor(None, os.read, master_fd, 1024)
if not data: # EOF
break
sys.stdout.write(data.decode())
sys.stdout.flush()

async def write_to_process(master_fd):
"""Asynchronously read from stdin and send input to the process."""
try:
loop = asyncio.get_event_loop()
while True:
try:
user_input = await loop.run_in_executor(None, sys.stdin.read, 1) # Read one character
if user_input == "\x04": # CTRL+D to signal EOF
os.write(master_fd, user_input.encode())
# print("CTRL+D")
break
if user_input == "":
break # EOF, such as CTRL-D
os.write(master_fd, user_input.encode())
except EOFError:
break
except Exception as e:
print("".join(traceback.format_exception(type(e), e, e.__traceback__)), file=sys.stderr)

# Run the main event loop with the command
command = ["ssh", "localhost"] # replace with your SSH command
asyncio.run(run_command(command))
print("ALL DONE")
sys.stdout.flush()


Подробнее здесь: https://stackoverflow.com/questions/791 ... run-return
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Все асинхронные работники ушли. Когда asyncio.run не возвращается?
    Anonymous » » в форуме Python
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous
  • Asyncio Async Funcitons вешает с Asyncio.gather. (Код работает без Asyncio.gather)
    Anonymous » » в форуме Python
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Asyncio.run() против asyncio.get_event_loop().run_until_complete()
    Anonymous » » в форуме Python
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Asyncio.run() против asyncio.get_event_loop().run_until_complete()
    Anonymous » » в форуме Python
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous
  • Asyncio.run() против asyncio.get_event_loop().run_until_complete()
    Anonymous » » в форуме Python
    0 Ответы
    7 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»