Python, использующий STDIN в дочернем процессе - PullRequest
5 голосов
/ 20 сентября 2011

Итак, у меня есть программа, в «основном» процессе я запускаю новый объект Process, который (что я хочу) - это чтение строк из STDIN и добавление их в объект Queue.

По сути, базовая настройка системы заключается в том, что существует процесс «получения команд», при котором пользователь будет вводить команды / запросы, и мне нужно передавать эти запросы другим подсистемам, работающим в отдельных процессах. Я хочу поделиться ими через многопроцессорную очередь, из которой другие системы могут читать.

То, что я имею (фокусируясь только на получении команд / запросов), в основном:

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

Как дела?

Ответы [ 4 ]

8 голосов
/ 02 апреля 2013

Я решил похожую проблему, передав исходный дескриптор файла stdin дочернему процессу и снова открыв его там.

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 в вновь открытом потоке.Я не знаю, насколько она надежна для более сложных систем.

3 голосов
/ 21 сентября 2011

Короче говоря, основной процесс и ваш второй процесс не используют один и тот же 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 ()

К сожалению, это не решает вашу проблему.Что ты пытаешься сделать?

1 голос
/ 17 октября 2013

Если вы не хотите передавать stdin в функцию целевых процессов, как в ответе @ 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, после которого будет предложено ввести данные, а затем квадрат ввода.

Только будьте осторожны, чтобы не иметь несколько дочерних процессов, читающих из одного и того же дескриптора одновременно, иначе все может стать ... запутанным.

0 голосов
/ 23 сентября 2011

Вы можете использовать многопоточность и поддерживать все это в одном процессе:

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
...