简体   繁体   English

如何使用Python中的线程模块写入命名管道?

[英]How to write to named pipe with the threading module in Python?

I am trying to write a program which communicates to an external program through named pipes. 我正在尝试编写一个程序,该程序通过命名管道与外部程序进行通信。 The python script does not know when the external program opens up the named pipe/file for reading, so the python script need to open the pipe in blocking mode, see open . python脚本不知道外部程序何时打开命名的管道/文件以供读取,因此python脚本需要以阻塞模式打开管道,请参见open If the python script opens in non-blocking mode and the external program has not opened for reading, the open statement will result in an error. 如果python脚本以非阻塞模式打开,并且尚未打开外部程序进行读取,则open语句将导致错误。

So to open in blocking mode, the python script could open the named pipe in a separate thread, and I have tried the threading module. 因此,要以阻塞模式打开,python脚本可以在单独的线程中打开命名管道,而我已经尝试了线程模块。 In the below example I just read from the named pipe in the main thread, but it produces the same error: 在下面的示例中,我只是从主线程中的命名管道中读取内容,但是会产生相同的错误:

import threading
import os

pipe_name = 'pipe_test'


class WriterNamedPipe(threading.Thread):

    def __init__(self, filepath, input):
        '''
        Write: generate that will output each line of input
        '''
        # Inherit
        threading.Thread.__init__(self, verbose = True)
        self.daemon = False
        self.filepath = filepath
        self.input = input
        self.start()

    def run(self):
        # Open blockingly
        with open(self.filepath, 'w') as f:
            f.write(self.input)

if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)

WriterNamedPipe(pipe_name, '1\n' * 100)

with open(pipe_name, 'r') as f:
    print f.read()

This would results in a hang/freeze: 这将导致挂起/冻结:

MainThread: <WriterNamedPipe(Thread-1, initial)>.start(): starting thread
Thread-1: <WriterNamedPipe(Thread-1, started 1078922160)>.__bootstrap(): thread started
Thread-1: <WriterNamedPipe(Thread-1, started 1078922160)>.__bootstrap(): normal return

Compilation hangup

However, a similar example from here works, but with os.fork : 但是, 这里的一个类似示例可以使用os.fork

import os, time, sys
pipe_name = 'pipe_test'

def child( ):
    pipeout = os.open(pipe_name, os.O_WRONLY)
    counter = 0
    while True:
        time.sleep(1)
        os.write(pipeout, 'Number %03d\n' % counter)
        counter = (counter+1) % 5

def parent( ):
    pipein = open(pipe_name, 'r')
    while True:
        line = pipein.readline()[:-1]
        print 'Parent %d got "%s" at %s' % (os.getpid(), line, time.time( ))

if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)  
pid = os.fork()    
if pid != 0:
    parent()
else:       
    child()

Why is the example with the threading module hanging? 为什么示例中的线程模块挂起?

This does probably not work due to the GIL . 由于GIL,这可能无法正常工作。 The open statement in the thread blocks the whole program. 线程中的open语句将阻塞整个程序。 This could be avoided by using multiprocessing module instead. 可以通过使用多处理模块来避免这种情况。

sure as @hakanc pointed out due to GIL it will block your process. 就像@hakanc指出的那样,由于GIL会阻止您的进程。 The os.fork is working because it actually spawn an subprocess instead of thread, which is not blocked by GIL. os.fork之所以起作用,是因为它实际上产生了一个子进程而不是线程,而该子进程并未被GIL阻止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM