python - input() 阻塞进程的使用

标签 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):

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()

最佳答案

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

解决此类阻塞问题的常用方法是使用进程而不是线程。如果将 InputCatcher 设为进程而不是线程,那么它就会成为操作系统可以独立调度的单独操作系统级进程,因此系统调用只会阻塞该进程,而不是主进程。

<小时/>

异常(exception),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)

关于python - input() 阻塞进程的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23081060/

相关文章:

python - 如何在我的 gentoo 上向 python2 添加 Tkinter 支持?

java - 守护线程未按预期工作

java - SpinLock 可扩展性和限制

python - 无法更改 matplotlib 中的刻度标签属性

python - 适用于 Google 日历 -> iPhone 的字符编码和 VALARM 以及 .ics 文件

Angular 4 - 获取输入值

C scanf() 问题?

html - Input type=number Safari 仍然允许带步进器的字母

python - 从 Python 向 shell 脚本传递参数

c - 产生新进程 v 线程的动机