我遇到多处理问题。如果我在线程中等待输入,则该过程无法启动。
将输入放入后台队列的类:
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()
答案 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())
您似乎已从代码中省略了一些管道,因此无法按原样运行。