input()阻止了进程的使用

时间:2014-04-15 10:29:16

标签: python multithreading input serial-port multiprocessing

我遇到多处理问题。如果我在线程中等待输入,则该过程无法启动。

将输入放入后台队列的类:

class InputCatcher(Thread):
    def __init__(self, input_queue):
        Thread.__init__(self)
        self.input_queue = input_queue

    def run(self):
        while True:
            self.input_queue.put(input()) # <<-- Without this it works!

无法启动的课程:

class Usb(Process):
    def __init__(self, port, ctrl=Controller()):
        Process.__init__(self)
        self.usb_port = port
        self.ctrl = ctrl


    def run(self):
        self.ctrl.usb_ports.append(self.usb_port)
        ser = Serial(self.usb_port, 115200)
        while True:
            dsl = ser.readline()
            self.ctrl.get_dataset_queue().put(['USBDS', dsl])
            print(dsl)

从:

开始
ic = InputCatcher(self.input_queue)
ic.setDaemon(True)
ic.start()

usbs = []
for port in usb_ports():
    if not port in ctrl.xbee_ports:
        usbs.append(Usb(port, ctrl))

for usb in usbs:
    usb.daemon = True
    usb.start()

2 个答案:

答案 0 :(得分:2)

当你调用input时,它会阻塞整个Python进程,而不仅仅是它运行的线程。这是因为从STDIN读取,比如从任何其他类似文件的对象读取,涉及到阻塞系统调用 - 也就是说,等待用户输入的input阻塞发生在操作系统级别,而不是在Python自己的线程管理代码中。 Python线程对操作系统进程调度程序基本上是不可见的,因此 Python本身被阻止。

阻止这类问题的常用方法是使用进程而不是线程。如果将InputCatcher设置为进程而不是线程,则它将成为操作系统可以独立调度的单独操作系统级进程,因此系统调用只会阻止 进程而不是主进程。


外,该Python自动closes STDIN when you spawn a process

因此,您需要在主进程中拥有队列的生产者,而在另一个进程中只需要使用者。这也是一个微不足道的适应 - 不要启动生产者(InputCatcher)运行,直到所有的消费者进程产生后。这涉及到移动线:

ic.start()

到两个循环下方。但在这种情况下,根本不需要背景 - 它不会与其他东西同时运行。因此,您可以完全忘记InputCatcher类,只需编写如下代码:

for usb in usbs:
    usb.daemon = True
    usb.start()

while True:
    input_queue.put(input())

您可能还想考虑一个特定的输入 - 比如空字符串 - 来结束程序。在主运行中输入使得通过结束循环非常简单:

while True:
    data = input('Type data; or enter to exit: ')
    if not data:
        break
    input_queue.put(data)

答案 1 :(得分:-1)

self.input_queue.put(input())

这意味着:要求用户立即输入 ,而不是将任何用户输入放入队列中。

看起来应该像

self.input_queue.put(lambda: input())

您似乎已从代码中省略了一些管道,因此无法按原样运行。