【问题标题】:Python, trying to get input from subprocess?Python,试图从子进程中获取输入?
【发布时间】:2012-06-15 20:26:08
【问题描述】:

main.py

import subprocess,sys
process = subprocess.Popen([sys.executable]+['example.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    out = process.stdout.read(1)
    if not out:
        out=process.stderr.read(1)
    if out == '' and process.poll() != None:
        break
    if out != '':
        print out

example.py

f=raw_input('WHats your favorite animal')

好的,我想知道如何检查主循环中的输入并为其提供一些数据。现在,当我使用 raw_input 时,我的程序会冻结。

这就是我想要的

while True:
    out = process.stdout.read(1)
    if not out:
        out=process.stderr.read(1)
    if out == '' and process.poll() != None:
        break
    #showing what i want
    if request_input==True:
        give_input('cat') #Give input to the raw_input
    #
    if out != '':
        print out

不知道有没有这样的功能。如果您需要更多解释,请发表评论。

【问题讨论】:

标签: python multiprocessing subprocess


【解决方案1】:

这并不是进行进程间通信的最佳方式,我建议您使用多处理或线程库以及队列或 PIPE 之类的东西来进行通信和同步。

队列是共享数据的最简单方式,一个进程输入一个值,另一个进程获取值。

我已经修改了你的原始代码,所以它现在可以工作了,注意 raw_input 不会刷新标准输出,如果那里没有任何东西它会挂起,http://code.activestate.com/lists/python-list/265749/ 这就是为什么你的代码只是在等待标准输出......

这很危险,它会产生死锁,使用风险自负,尝试其他方法。

import sys
print 'Whats your favorite animal\n' #raw_input doesn't flush :( and we want to read in a whole line
sys.stdout.flush()
f = raw_input()
print f

以及对应的main.py

import subprocess, sys, os
process = subprocess.Popen([sys.executable]+['example.py'],
     stdout = subprocess.PIPE, stderr = subprocess.PIPE, stdin = subprocess.PIPE)

while True:
    if process.poll() != None:
        break
    request_input = process.stdout.readline() # read line, this will wait until there's actually a line to read.
    if request_input == "Whats your favorite animal\n":
        print 'request: %s sending: %s' % (request_input, 'cat')
        process.stdin.write('cat\n')
       process.stdin.flush()

【讨论】:

  • "request_input == "Whats your favorite animal\n":",我只是在寻找raw_input函数被访问时的一般情况。
  • 我觉得这有点棘手,因为 raw_input 通常只是从标准输入读取该文件描述符对象上的 readline 调用,我正在考虑检查该文件是否已打开,但我认为它是自动打开的,一旦开始执行:(对不起。多处理/线程可能是最好的,除非你真的需要 raw_input...
  • 啊,我明白了,我对任何解决方案都持开放态度,我想做的是一个 python IDE(为了好玩)。 ide中的输入有点重要,所以我需要它。我想我只是继续寻找答案,再次感谢您的回复
  • 没问题,有趣,我用过的最好的python IDE是pycharm,虽然不是免费的,但它很棒,你可以看看,也许会有一些想法:)
  • @user1357159 我正在浏览python源代码,我会让你。
【解决方案2】:

编辑:好像我误解了你的问题,对此感到抱歉。

这并不像你想象的那么简单:

你必须使用select来检查stdin中是否有可用的数据,如果有数据,请阅读!

小例子:

STDIN, STDOUT = 0, 1

while not process.poll() is None:
    out = process.stdout.read(1)

    if not out:
        break

    try:
        fds = select.select([STDIN], [], [])[0]
    except select.error:
        pass
    else:
        if STDIN in fds:
            data = os.read(STDIN, 1024)

            if data_requested:
                process.stdin.write(data)

要选择的信息:http://docs.python.org/library/select.html#module-selecthttp://linux.die.net/man/2/selecthttp://en.wikipedia.org/wiki/Select_(Unix)

不确定这是否适用于 Windows,因为 Windows 仅支持套接字上的select。 SO相关问题:What is the best epoll/kqueue/select equvalient on Windows?

【讨论】:

    【解决方案3】:

    尝试使用多处理模块

    from multiprocessing import Process, Value, Array
    
    def f(n, a):
        n.value = 3.1415927
        for i in range(len(a)):
            a[i] = -a[i]
    
    if __name__ == '__main__':
        num = Value('d', 0.0)
        arr = Array('i', range(10))
    
        p = Process(target=f, args=(num, arr))
        p.start()
        p.join()
    
        print num.value
        print arr[:]
    

    【讨论】:

      【解决方案4】:

      除非你坚持使用“raw python”,否则最好使用 pexpect 模块。我已经在你的 example.py 中添加了一个输出,否则它一点也不好玩。

      这里是example.py:

          f=raw_input('WHats your favorite animal')
          print f.upper()
      

      这是您要查找的 pexpect-example.py:

          # see http://pexpect.sourceforge.net/pexpect.html
          import pexpect
      
          PY_SCRIPT = 'example.py'
      
          child = pexpect.spawn('python %s' % PY_SCRIPT)
      
          child.expect ('WHats your favorite animal')
      
          # comment out these three lines if you run unmodified example.py script
          child.setecho(False)
          child.sendline ('cat')
          print PY_SCRIPT, 'said:', child.readline()
      

      【讨论】:

      • 您不需要 print f.upper() 调用 - abb 只是添加它来显示输出以确认脚本有效。答案的重要部分,即 pexpect 模块,几乎可以肯定是最强大的解决方案。
      • 对不起,我只是浏览了答案。我已经研究过了,它很好,但由于 pexpect 使用的模块,它只能在 linux 上运行。
      • 另外,使用 "child.expect ('WHats your favorite animal')" 对我不起作用,因为我正在寻找任何 raw_input 案例
      猜你喜欢
      • 1970-01-01
      • 2015-01-21
      • 2015-06-08
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 2016-11-17
      • 2020-05-03
      • 1970-01-01
      相关资源
      最近更新 更多