2011-09-20 99 views
4

所以我有一个程序,在“main”进程中,我启动了一个新的Process对象(我想要的)是从STDIN读取行并将它们附加到Queue对象。在子进程中使用STDIN的Python

本质上来说,基本的系统设置是有一个“命令获取”过程,用户将输入命令/查询,并且我需要将这些查询提供给运行在不同进程中的其他子系统。我的想法是通过其他系统可读取的多处理队列来共享这些队列。

我所(侧重于刚刚得到的命令/查询)基本上是:

def sub_proc(q): 
    some_str = "" 
    while True: 
     some_str = raw_input("> ") 
     if some_str.lower() == "quit": 
      return 
     q.put_nowait(some_str) 

if __name__ == "__main__": 
    q = Queue() 
    qproc = Process(target=sub_proc, args=(q,)) 
    qproc.start() 
    qproc.join() 

    # now at this point q should contain all the strings entered by the user 

的问题是,我得到:

Process Process-1: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
    File "/home/blah/blah/blah/blah.py", line 325, in sub_proc 
    some_str = raw_input("> ") 
    File "/randompathhere/eclipse/plugins/org.python.pydev_2.1.0.2011052613/PySrc/pydev_sitecustomize/sitecustomize.py", line 181, in raw_input 
    ret = original_raw_input(prompt) 
EOFError: EOF when reading a line 

怎么办?

+0

相关:[有没有办法将'stdin'作为参数传递给python中的另一个进程? /8976962](https://stackoverflow.com/questions/8976962/is-there-any-way-to-pass-stdin-as-an-argument-to-another-process-in-python/) – n611x007

+0

note [评论](https://stackoverflow.com/questions/8976962/is-there-any-way-to-pass-stdin-as-an-argument-to-another-process-in-python/8981813#comment11253203_8976962)的(http://stackoverflow.com/users/24718/monkut):“类似于[你如何从Python中的stdin读取?/1450393](http://stackoverflow.com/questions/1450393/如何从Python读取stdin)“ – n611x007

回答

3

总之,主进程和你的第二个进程不共享相同的STDIN。

from multiprocessing import Process, Queue 
import sys 

def sub_proc(): 
    print sys.stdin.fileno() 

if __name__ == "__main__": 
    print sys.stdin.fileno() 
    qproc = Process(target=sub_proc) 
    qproc.start() 
    qproc.join() 

运行这一点,你应该得到sys.stdin.fileno)两种不同的结果(

不幸的是,这并不解决您的问题。你想做什么?

+0

本质上,我想要一个系统,用户可以在一个进程中输入文本查询/命令,并将这些查询转移到另一个进程。 –

+0

为什么不从主进程的标准输入读取并将它们推入队列以便由辅助进程处理? –

+0

由于系统构建起来很困难,并且似乎应该可以在进程之间简单共享相同的stdin。 –

0

你可以使用线程,并保持它都在同一过程:

from multiprocessing import Queue 
from Queue import Empty 
from threading import Thread 

def sub_proc(q): 
    some_str = "" 
    while True: 
     some_str = raw_input("> ") 
     if some_str.lower() == "quit": 
      return 
     q.put_nowait(some_str) 

if __name__ == "__main__": 
    q = Queue() 
    qproc = Thread(target=sub_proc, args=(q,)) 
    qproc.start() 
    qproc.join() 

    while True: 
     try: 
      print q.get(False) 
     except Empty: 
      break 
+1

但是,GIL的线程受损(在任何给定时间只能有一个线程执行)。一旦命令进入队列,其他进程可以处理该项目,而“读取输入”进程可以从用户处获得下一个项目/命令(或者这是想法)。由于全局解释器锁(GIL),使用线程将不可能, –

6

我通过将原来的标准输入文件描述符子进程,并重新打开它有解决类似的问题。

def sub_proc(q,fileno): 
    sys.stdin = os.fdopen(fileno) #open stdin in this process 
    some_str = "" 
    while True: 
     some_str = raw_input("> ") 

     if some_str.lower() == "quit": 
      return 
     q.put_nowait(some_str) 

if __name__ == "__main__": 
    q = Queue() 
    fn = sys.stdin.fileno() #get original file descriptor 
    qproc = Process(target=sub_proc, args=(q,fn)) 
    qproc.start() 
    qproc.join() 

这适用于我相对简单的情况。我甚至可以在重新打开的流上使用readline模块。我不知道它对于更复杂的系统有多强大。

1

如果你不想标准输入传递给目标进程的功能,如在@ Ashelly的答案,或者只是需要做许多不同的方法,你可以通过初始化参数与multiprocessing.Pool做到这一点:

import os, sys, multiprocessing 

def square(num=None): 
    if not num: 
     num = int(raw_input('square what? ')) 
    return num ** 2 

def initialize(fd): 
    sys.stdin = os.fdopen(fd) 

initargs = [sys.stdin.fileno()] 
pool = multiprocessing.Pool(initializer=initialize, initargs=initargs) 
pool.apply(square, [3]) 
pool.apply(square) 

上面的例子将打印数字9,然后提示输入,然后输入数字的平方。

只是要小心不要让多个子进程在同一时间从同一个描述符中读取,否则可能会令人困惑。