在另一个线程试图关闭()后线程在 process.stdout.read 上阻塞
thread blocked on process.stdout.read after another thread tried to close() it
我有两个线程,一个想打断另一个。
线程 1:
self.running = True
p = subprocess.Popen (... stdout = subprocess.PIPE)
self.closer = p.stdout
print ("Starting to read.")
while True:
line = p.stdout.read ()
if not line:
print ("Finishing")
break
self.running = False
线程 2
print ("About to close.")
self.closer.close ()
while self.running:
time.sleep (0.1)
print ("Finished")
这没有用。输出是
Starting to read.
About to close.
看起来 p.stdout.read()
仍然被阻止。
一段时间后,p.stdout.read()
抛出异常
ValueError: PyMemoryView_FromBuffer(): info->buf must not be NULL
此外,我认为线程 2 的 close()
会阻塞,直到发生此异常。
中断正在以阻塞方式从进程读取的线程的正确方法是什么?
unix
系统的解决方案:
您需要允许 Thread 1
检查关闭标志的状态而不是无限期地等待读取,例如在循环中使用 poll
对象,如下所示:
import select
import subprocess
process = subprocess.Popen("ls -lah", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
poll_obj = select.poll()
poll_obj.register(process.stdout, select.POLLIN) # ready for reading
closed = False
while not closed:
if poll_obj.poll(1):
line = process.stdout.readline()
print(line)
我有两个线程,一个想打断另一个。
线程 1:
self.running = True
p = subprocess.Popen (... stdout = subprocess.PIPE)
self.closer = p.stdout
print ("Starting to read.")
while True:
line = p.stdout.read ()
if not line:
print ("Finishing")
break
self.running = False
线程 2
print ("About to close.")
self.closer.close ()
while self.running:
time.sleep (0.1)
print ("Finished")
这没有用。输出是
Starting to read.
About to close.
看起来 p.stdout.read()
仍然被阻止。
一段时间后,p.stdout.read()
抛出异常
ValueError: PyMemoryView_FromBuffer(): info->buf must not be NULL
此外,我认为线程 2 的 close()
会阻塞,直到发生此异常。
中断正在以阻塞方式从进程读取的线程的正确方法是什么?
unix
系统的解决方案:
您需要允许 Thread 1
检查关闭标志的状态而不是无限期地等待读取,例如在循环中使用 poll
对象,如下所示:
import select
import subprocess
process = subprocess.Popen("ls -lah", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
poll_obj = select.poll()
poll_obj.register(process.stdout, select.POLLIN) # ready for reading
closed = False
while not closed:
if poll_obj.poll(1):
line = process.stdout.readline()
print(line)