我正在使用子进程模块启动子进程并连接到它的输出流(stdout).我希望能够在其标准输出上执行非阻塞读取.有没有办法让.readline非阻塞或在我调用之前检查流上是否有数据.readline
?我希望这是可移植的,或至少在Windows和Linux下工作.
这是我现在如何做到的(.readline
如果没有数据可用,则阻止它):
p = subprocess.Popen('myprogram.exe', stdout = subprocess.PIPE)
output_str = p.stdout.readline()
Run Code Online (Sandbox Code Playgroud) python脚本控制Linux上的外部应用程序,通过管道将输入传递到外部应用程序stdin,并通过外部应用程序stdout的管道读取输出.
问题是对管道的写入是按块而不是按行缓冲的,因此在控制脚本通过外部应用程序中的printf接收数据输出之前会发生延迟.
无法更改外部应用程序以添加显式fflush(0)调用.
我有一个子进程,要么退出返回码,要么问一些东西,等待用户输入.
我想检测过程何时提出问题并立即退出.过程提出问题的事实足以让我决定系统的状态.
问题是我无法阅读这个问题,因为子进程可能不会刷新标准输出.所以我不能依赖解析subprocess.Popen().stdout
:当试图读取它时,它会阻塞因为首先读取输入.
有点像这样
# ask.py, just asks something without printing anything if a condition is met
# here, we'll say that the condition is always met
input()
Run Code Online (Sandbox Code Playgroud)
当然,实际的子进程是第三方二进制文件,我无法轻松修改它以添加必要的刷新调用,这将解决它.
我还可以尝试相当于Windows unbuffer
(相当于Windows上的unbuffer程序?)的Windowswinpty
,这可能(可能)允许我检测输出并解决我当前的问题,但我想保持简单和我想首先解决标准输入问题...
我想......嗯,很多事情不工作,包括试图通过假文件作为stdin
参数,它不起作用,因为subprocess
需要的fileno
文件,我们不能给它的垃圾...
p = subprocess.Popen(["python","ask.py"],...)
Run Code Online (Sandbox Code Playgroud)
使用communicate
字符串也不起作用,因为您无法控制何时读取字符串以供应给子进程(可能通过系统管道).
这些问题很有希望,但要么依赖标准输出,要么仅适用于Linux
我目前正在做的是超时运行进程,如果超时,我决定程序被阻止.但它花费了超时等待时间.如果我能stdin
在子进程读取后尽快做出决定,那就更好了.
我想知道是否有一个本机python解决方案(可能使用ctypes
和Windows扩展)来检测从stdin读取.但是,本机解决方案不使用Python而是使用非Microsoft专有语言.