Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-如何在subprocess.Popen中从管道进行非阻塞读取?_Python_Pipe_Subprocess - Fatal编程技术网

Python-如何在subprocess.Popen中从管道进行非阻塞读取?

Python-如何在subprocess.Popen中从管道进行非阻塞读取?,python,pipe,subprocess,Python,Pipe,Subprocess,上周我也发布了类似的帖子,这篇帖子反映了我面临的考验和问题 通过Popen调用的程序是一个命令行程序。我使用一个线程从队列中读取一个项目,并将其发送到stdin,然后从stdout获得响应。但是,它将挂起proc.stdout.read()中的。上周五,我确实看到它在预期输出下运行良好,但当我今天做一些更改时,它挂起了。我所做的更改是将read()替换为readlines(),并使用循环迭代结果。我知道readlines()可能会阻塞,但当我上周五使用read()将代码反转到原来的位置时,它也会

上周我也发布了类似的帖子,这篇帖子反映了我面临的考验和问题

通过Popen调用的程序是一个命令行程序。我使用一个线程从队列中读取一个项目,并将其发送到stdin,然后从stdout获得响应。但是,它将挂起
proc.stdout.read()
中的。上周五,我确实看到它在预期输出下运行良好,但当我今天做一些更改时,它挂起了。我所做的更改是将
read()
替换为
readlines()
,并使用循环迭代结果。我知道
readlines()
可能会阻塞,但当我上周五使用
read()
将代码反转到原来的位置时,它也会阻塞。我现在完全迷路了。有什么可能的原因吗

下面是从队列中获取一个句子并将其提供给java程序以获取响应的代码:

''' below is the code for worker thread. '''
def readQueue(proc, queue):
    print 'enter queueThread.\n'
    global notEmpty
    notEmpty = True
    while notEmpty:
        try:
            sen = queue.get()
            proc.stdin.write(sen.strip())
            res = proc.stdout.read()
            print res.strip(), ' ', sen
            queue.task_done()
        except Empty:
            break
    print 'leave queueThread.'
下面的主线程是从文件中读取每一行,并将其放入工作线程逐项处理的队列中:

def testSubprocess():
    ee = open('sentences.txt', 'r')
    #ff = open('result.txt', 'w')   # print it to stdout first before really write to a file. 
    lines = ee.readlines()
    cmd = ['java', 
           '-cp', 'someUsefulTools.jar', 
           'className', 
           '-stdin',]   # take input from stdin
    proc = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE, bufsize=-1, universal_newlines=True)
    q = Queue()
    for sen in lines:
        q.put(sen.strip())
    readThread = Thread(target=readQueue, args=(proc, q))
    readThread.daemon = True
    readThread.start()
    print 'Main thread is waiting...\n'
    q.join()
    global notEmpty; notEmpty = False
    print 'Done!'

子流程中的管道是类似文件的对象

这些对象上的方法
read()
会将所有内容读取到内存中,直到达到EOF。如果您不指定应该读取多少,请参阅文档:

如果不希望出现这种行为,则必须设置要读取的大小。尝试将其设置为1字节


这同样适用于
readlines()
,请参阅文档:

如果我误解了您的代码并且这不起作用,请道歉,但是我发现我可以阻止管道以这种方式阻塞。(我对python中的线程没有太多经验)在定义“proc”之后,添加以下内容:“fcntl.fcntl(proc,fcntl.F_SETFL,os.O_NONBLOCK)”如果proc被定义为“pipe”类型,那么应该停止阻塞。您可能需要导入fcntl。@我不确定是否正确,似乎“fcntl”用于linux/unix环境,对吗?(我的工作环境是windows)假设您向java程序发送一个句子:如何知道何时停止读取响应:它始终是10字节还是始终是一行,或者您希望一直读取到EOF,即每个进程只能回答一个问题?已尝试并将大小设置为读取。问题依旧。几乎想放弃并转向。一些程序在通过
pexpect
执行时可能会表现不同,因为程序可以检测它们是否在终端(TTY设备)中运行。我不知道Java程序是否能做到这一点。例如,如果在我的系统上运行
ps aux
ps
检测到终端只有80个字符宽,并相应地缩短行数。如果我们将输出通过管道传输到一个文件中(与子流程类似),它将不知道终端的宽度,因此不会缩短行数。