为什么 Python Popen 调用在与服务器相同的进程中运行时会遇到死锁?

问题描述 投票:0回答:0

我有一点经典的 Python

Popen
问题。

下面是我用来从

Popen
调用创建异步迭代器的代码。在大多数情况下,它是有效的。但是,有时它会陷入僵局;当与
uvicorn
服务器在同一进程中运行时,它尤其经常这样做。

import os
import subprocess
from threading import Thread
from queue import Queue
from typing import IO, AsyncIterator, Dict, Iterable, Optional, Tuple
from enum import Enum, IntEnum
import sys


class StdFd(IntEnum):
    stdout = 0
    stderr = 1
    stdeof = 2

def read_fd(pipe :  IO[bytes], queue : Queue[Tuple[StdFd, bytes]], fd : Optional[StdFd] = StdFd.stdout):
    try:
        with pipe:
            for line in iter(pipe.readline, b""):
                queue.put((fd, line))
    finally:
        queue.put((StdFd.stdeof, b""))

async def call_with_env(cmd : Iterable[str], *, env : Dict[str, str])->AsyncIterator[Tuple[StdFd, bytes]]:
    
    queue : Queue[Tuple[StdFd, bytes]] = Queue()
    process = subprocess.Popen(
        cmd,
        stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE, 
        env=env,
    )
   
    Thread(target=read_fd, args=[process.stdout, queue, StdFd.stdout]).start()
    Thread(target=read_fd, args=[process.stderr, queue, StdFd.stderr]).start()
    
    hits = 0
    while hits < 2:
        try:
            next = queue.get(block=False)
            
            if next[0] == StdFd.stdeof:
                hits += 1
                continue
        
            yield next
        except Exception:
            continue
        
    yield (StdFd.stdeof, b"")

我试过冲洗所有东西。这还没有改变。接下来可以检查什么?

我在调用

process.communicate()
时也得到了相同的行为,尽管这无论如何都不会产生所需的行为。

Python版本为3.10.10。我遇到了与

asyncio.create_subprocess_exec
相同的行为。

python subprocess
© www.soinside.com 2019 - 2024. All rights reserved.