我想从子进程获取输出,然后根据前面的输出为该进程提供命令。当程序需要进一步输入时,我需要做这个可变的次数。 (如果可能,我还需要能够隐藏子进程命令提示符)。从python子进程获取输出并给出命令
我觉得这将是一件容易的事,因为我已经看到这个问题在2003年的帖子中讨论过,它接近2012年,它似乎是一个相当普遍的需求,真的好像它应该是一个基本的部分任何编程语言。显然,我错了,不知何故,差不多9年后,仍然没有以稳定,非破坏性,独立于平台的方式完成这项任务的标准方法!
我对文件I/O和缓冲或线程并不十分了解,所以我宁愿选择一个尽可能简单的解决方案。如果有一个模块实现了与python 3.x兼容的模块,我将非常乐意下载它。我意识到有多个问题基本上提出了同样的问题,但我还没有找到解决我试图完成的简单任务的答案。
这是我迄今为止基于各种来源的代码;但是我绝对不知道下一步该怎么做。我所有的尝试都以失败告终,有些设法使用了我CPU的100%(基本上什么都不做),并且不会退出。
import subprocess
from subprocess import Popen, PIPE
p = Popen(r'C:\postgis_testing\shellcomm.bat',stdin=PIPE,stdout=PIPE,stderr=subprocess.STDOUT shell=True)
stdout,stdin = p.communicate(b'command string')
如果我的问题是不清楚我张贴的样本批处理文件中,我展示了一种情况,即有必要多个命令发送给子进程(如果你输入了不正确的命令字符串程序文字循环)。
@echo off
:looper
set INPUT=
set /P INPUT=Type the correct command string:
if "%INPUT%" == "command string" (echo you are correct) else (goto looper)
如果有人可以帮助我,我会非常感激,我相信很多人也会这样!这里
编辑是使用eryksun的代码(下一篇文章)的功能代码:
import subprocess
import threading
import time
import sys
try:
import queue
except ImportError:
import Queue as queue
def read_stdout(stdout, q, p):
it = iter(lambda: stdout.read(1), b'')
for c in it:
q.put(c)
if stdout.closed:
break
_encoding = getattr(sys.stdout, 'encoding', 'latin-1')
def get_stdout(q, encoding=_encoding):
out = []
while 1:
try:
out.append(q.get(timeout=0.2))
except queue.Empty:
break
return b''.join(out).rstrip().decode(encoding)
def printout(q):
outdata = get_stdout(q)
if outdata:
print('Output: %s' % outdata)
if __name__ == '__main__':
#setup
p = subprocess.Popen(['shellcomm.bat'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0, shell=True) # I put shell=True to hide prompt
q = queue.Queue()
encoding = getattr(sys.stdin, 'encoding', 'utf-8')
#for reading stdout
t = threading.Thread(target=read_stdout, args=(p.stdout, q, p))
t.daemon = True
t.start()
#command loop
while p.poll() is None:
printout(q)
cmd = input('Input: ')
cmd = (cmd + '\n').encode(encoding)
p.stdin.write(cmd)
time.sleep(0.1) # I added this to give some time to check for closure (otherwise it doesn't work)
#tear down
for n in range(4):
rc = p.poll()
if rc is not None:
break
time.sleep(0.25)
else:
p.terminate()
rc = p.poll()
if rc is None:
rc = 1
printout(q)
print('Return Code: %d' % rc)
然而,当脚本是从命令运行提示会发生以下情况:
C:\Users\username>python C:\postgis_testing\shellcomm7.py
Input: sth
Traceback (most recent call last):
File "C:\postgis_testing\shellcomm7.py", line 51, in <module>
p.stdin.write(cmd)
IOError: [Errno 22] Invalid argument
看来,程序在从命令提示符运行时关闭。有任何想法吗?
非常感谢你为这个它完全处于空闲,但是当我运行修改后的代码(见我在原来的职位编辑)它给了我下面的错误 C:\ Users \用户名>蟒蛇Ç :\ postgis_testing \ shellcomm7.py 输入:某物 回溯(最近通话最后一个): 文件 “C:\ postgis_testing \ shellcomm7.py” 51行,在 p.stdin.write(CMD) IO错误: [Errno 22]无效的参数 从命令提示符运行时,程序似乎关闭。有任何想法吗? –
THX1138
@ THX1138:我修改了循环以查询进程并在请求输入之前检查stdin。如果流程退出,它会中断。我也从'read_stdout'参数中删除了过程对象;它在我的初稿中错误地留下了。 – eryksun
当我从命令提示符运行新代码时,出现以下错误: C:\ Users \ username> python C:\ postgis_testing \ shellcomm8.py Traceback(最近调用最后一次): 文件“C:\ postgis_testing \ shellcomm8.py “第38行,在 BUFSIZE = 0) 文件 ”C:\ Python32 \ lib中\ subprocess.py“,线路741,在__init__ restore_signals,start_new_session) 文件” C:\ Python32 \ lib中\ subprocess.py“,第960行,在_execute_child startupinfo) WindowsError:[错误2]系统找不到指定的文件 –
THX1138