input()阻止了进程的使用 [英] input() is blocking the use of processes

查看:245
本文介绍了input()阻止了进程的使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对多重处理有疑问.如果我正在等待线程中的输入,则该过程无法启动.

I have a problem with multiprocessing. If I am waiting for input in a thread the process is not starting.

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

The class to put the input into a queue in the background:

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

推荐答案

调用input时,它阻塞了整个Python进程,而不仅仅是它运行的线程.任何其他类似文件的对象,都涉及进行阻塞的系统调用-即input阻塞以等待用户输入发生在操作系统级别,而不是在Python自己的线程管理代码内部. Python线程对于OS进程调度程序基本上是不可见的,因此 Python本身被阻塞了.

When you call input, it is blocking the entire Python process, not just the thread it runs in. This happens because reading from STDIN, like reading from any other file-like object, involves making a blocking syscall - that is, input blocking to wait for user input happens at the OS level, rather than inside Python's own thread management code. Python threads are essentially invisible to the OS process scheduler, so Python itself gets blocked.

解决此类问题的常用方法是使用进程而不是线程.如果将InputCatcher设置为进程而不是线程,则它将成为OS可以独立调度的单独的OS级进程,因此syscall仅阻止那个进程,而不阻塞主进程.

The usual way around blocking problems like this is to use processes instead of threads. If you make InputCatcher into a process rather than a thread, then it becomes a separate OS-level process that the OS can schedule independently, and so the syscall will only block that process and not the main one.

除了,Python在生成进程时自动关闭STDIN .

Except, that Python automatically closes STDIN when you spawn a process.

因此,您需要在主流程中有队列的生产者,而在另一个流程中只有消费者.这也是一个微不足道的调整-在所有消费程序都在之后出现之前,不要启动生产程序(InputCatcher).这涉及到移动线:

So, you would need to have the producer for the queue in the main process, and only the consumer in another one. This is also a trivial adaption - don't start the producer (InputCatcher) running until after all of the consumer processes have spawned. That involves moving the line:

ic.start()

到两个循环下面.但是在这种情况下,根本不需要将其作为背景-它不会与其他事物同时运行.因此,您可以完全忘记InputCatcher类,而只需编写如下代码:

to below the two loops. But in this case, there's no need for that to be backgrounded at all - it doesn't run simultaneously with other things. So, you can forget about the InputCatcher class entirely, and just write your code like this:

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

while True:
    input_queue.put(input())

您可能还想考虑一个特定的输入-例如,空字符串-结束程序.通过结束循环,使输入在主运行中变得非常容易:

You might also want to consider a particular input - say, the empty string - to end the program. Having the input in the main run makes this really easy by just ending the loop:

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

这篇关于input()阻止了进程的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆