python subprocess.Popen stdin.write

时间:2015-05-08 21:48:20

标签: python stdin popen

我是python的新手,想要打开一个windows cmd提示符,启动一个进程,让进程保持运行状态,然后向同一个运行进程发出命令。

命令会改变,所以我不能在下面的cmdline变量中包含这些命令。此外,该过程需要10-15秒才能启动,因此我不想浪费时间等待进程每次启动和运行命令。只想开始一次处理。并在同一过程中根据需要运行快速命令

我希望使用subprocess.Popen来完成这项工作,尽管我对更好的方法持开放态度。请注意,我的运行流程不是cmd,但我只是以此为例

import subprocess
cmdline = ['cmd', '/k']
cmd = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

cmd.stdin.write("echo hi")       #would like this to be written to the cmd prompt
print cmd.stdout.readline()      #would like to see 'hi' readback

cmd.stdin.write("echo hi again") #would like this to be written to the cmd prompt
print cmd.stdout.readline()      #would like to see 'hi again' readback

结果不是我所期望的。好像stdin.write命令实际上并没有进入,并且readline冻结而没有任何东西可读。

我尝试过popen.communicate()而不是写/读取,但它会杀死进程。我已经尝试在Popen行中设置bufsize,但这并没有太大的区别

3 个答案:

答案 0 :(得分:1)

您的评论表明您通过stdin输入混淆命令行参数。也就是说,system-console.exe程序接受script=filename参数这一事实并不意味着您可以通过stdin向命令发送与命令相同的字符串,例如,python可执行文件接受-c "print(1)"命令 - 如果你将它作为命令传递给Python shell,那么它是一个SyntaxError

因此,第一步是使用正确的语法。假设system-console.exe自己接受文件名:

#!/usr/bin/env python3
import time
from subprocess import Popen, PIPE

with Popen(r'C:\full\path\to\system-console.exe -cli -', 
           stdin=PIPE, bufsize=1, universal_newlines=True) as shell:
    for _ in range(10):
        print('capture.tcl', file=shell.stdin, flush=True)
        time.sleep(5)

注意:如果您重定向了多个流,例如stdin,stdout,那么您应该同时读取/写入两个流(例如,使用多个线程),否则很容易使程序死锁。

相关:

第二步和以下步骤可能必须处理子进程一侧的缓冲问题(在Windows上不受欢迎),system-console是否允许重定向其stdin / stdout或者是否与其一起使用直接控制台和字符编码问题(管道中的各种命令如何编码文本)。

答案 1 :(得分:0)

如果您想实时查看输出,则需要使用它:

import subprocess
cmdline = ['cmd', '/k']
cmd = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE)


cmd.stdin.write("echo hi\n")#would like this to be written to the cmd prompt
for line in iter(cmd.stdout.readline,""):
    print line
    cmd.stdin.write("echo hi again\n")#would like this to be written to the cmd prompt

不确定您要做什么,但如果您想在获得某些输出时输入某些数据,那么我建议您使用pexpect

答案 2 :(得分:0)

以下是我测试过的一些代码,它们正在使用Windows 10,Quartus Prime 15.1和Python 3.5

import subprocess

class altera_system_console:
    def __init__(self):
        sc_path = r'C:\altera_lite\15.1\quartus\sopc_builder\bin\system-console.exe --cli --disable_readline'
        self.console = subprocess.Popen(sc_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

    def read_output(self):
        rtn = ""
        loop = True
        i = 0
        match = '% '
        while loop:
            out = self.console.stdout.read1(1)
            if bytes(match[i],'utf-8') == out:
                i = i+1
                if i==len(match):
                    loop=False
            else:
                rtn = rtn + out.decode('utf-8')
        return rtn

    def cmd(self,cmd_string):
        self.console.stdin.write(bytes(cmd_string+'\n','utf-8'))
        self.console.stdin.flush()

c = altera_system_console()
print(c.read_output())
c.cmd('set jtag_master [lindex [get_service_paths master] 0]')
print(c.read_output())
c.cmd('open_service master $jtag_master')
print(c.read_output())
c.cmd('master_write_8 $jtag_master 0x00 0xFF')
print(c.read_output())