Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.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 如何运行子进程、在GUI中显示其输出并允许终止它?_Python - Fatal编程技术网

Python 如何运行子进程、在GUI中显示其输出并允许终止它?

Python 如何运行子进程、在GUI中显示其输出并允许终止它?,python,Python,我一直在尝试编写一个应用程序来运行子流程,并(除其他外)在GUI中显示它们的输出,并允许用户单击按钮取消它们。我开始这样的过程: queue = Queue.Queue(500) process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) iothread = threading.Thread( target=simple_io_thread,

我一直在尝试编写一个应用程序来运行子流程,并(除其他外)在GUI中显示它们的输出,并允许用户单击按钮取消它们。我开始这样的过程:

queue = Queue.Queue(500)
process = subprocess.Popen(
    command,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT)
iothread = threading.Thread(
    target=simple_io_thread,
    args=(process.stdout, queue))
iothread.daemon=True
iothread.start()
其中简单io线程定义如下:

def simple_io_thread(pipe, queue):
    while True:
        line = pipe.readline()
        queue.put(line, block=True)
        if line=="":
            break
这很有效。在我的UI中,我定期从队列中执行非阻塞“get”。但是,当我想要终止子流程时,我的问题就出现了。(子进程是一个任意进程,不是我自己写的。)我可以使用terminate方法来终止进程,但我不知道如何保证我的I/O线程将终止。它通常会阻塞管道上的I/O。在我终止流程后的某段时间内,这可能会结束,也可能不会结束。(如果子进程产生了另一个子进程,我可以杀死第一个子进程,但第二个子进程仍将保持管道打开。我甚至不知道如何让这样的子进程干净地终止。)之后,I/O线程将尝试将输出排队,但我不想承诺无限期地从队列中读取


理想情况下,我希望有某种方法来请求终止子进程,在短时间内阻塞(在终止进程的代码中,您也可以显式地
os.close()
线程正在读取的管道?

我知道这是一篇老文章,但如果它仍然对任何人都有帮助,我认为您的问题可以通过将subprocess.Popen实例传递给io_线程而不是它的输出流来解决。 如果这样做,则可以将
while True:
行替换为
while process.poll()==None:

检查子流程返回代码;如果流程尚未完成,则没有返回代码(即
process.poll()==None
)。然后,如果line==”:break,则可以删除

我来这里是因为我今天写了一个非常类似的脚本,我得到了这些:-
IOError:close()在对同一文件对象执行并发操作时被调用。
错误。

同样,如果有帮助,我认为我的问题源于(我的)io_线程执行了一些过于高效的垃圾收集,并关闭了我给它的文件句柄(我可能错了,但它现在工作了…)我的不同之处在于它不是守护进程,它通过subprocess.stdout进行迭代,而不是使用while循环..即:-

def io_thread(subprocess,logfile,lock):
    for line in subprocess.stdout:
        lock.acquire()
        print line,
        lock.release()
        logfile.write( line )

我可能还应该提到,我将bufsize参数传递给subprocess.Popen,以便对其进行行缓冲。

这可能已经足够老了,但对来自搜索引擎的人仍然有用

它显示该消息的原因是,在子进程完成后,它关闭了文件描述符,因此,守护进程线程(并发运行)将尝试使用这些关闭的描述符来引发错误

my_thread.join()
print my_thread.is_alive()
my_popen.communicate()
通过在子进程wait()或communicate()方法之前加入线程,应该足以抑制错误

my_thread.join()
print my_thread.is_alive()
my_popen.communicate()

您应该关闭写入管道…但是在编写代码时,您无法访问它。要执行此操作,您应该

  • 用板条箱装烟斗
  • 将写入管道文件id传递给
    Popen
    stdout
  • 使用读取管道文件
    simple\u io\u thread
    读取行
  • 现在可以关闭写入管道,读取线程将正常关闭

    queue = Queue.Queue(500)
    r, w = os.pipe()
    process = subprocess.Popen(
        command,
        stdout=w,
        stderr=subprocess.STDOUT)
    iothread = threading.Thread(
        target=simple_io_thread,
        args=(os.fdopen(r), queue))
    iothread.daemon=True
    iothread.start()
    
    现在

    os.close(w)
    

    您可以关闭管道,
    iothread
    将毫无例外地关闭。

    调用process.stdout.close()抛出:IOError:close()在对同一文件对象执行并发操作期间调用。调用os.close(process.stdout.fileno())似乎可以工作,但在丢弃进程时出现异常:文件对象析构函数中的关闭失败:IOError:[Errno 9]错误的文件描述符至少有一个人认为它有用!
    my_thread.join()
    print my_thread.is_alive()
    my_popen.communicate()
    
    queue = Queue.Queue(500)
    r, w = os.pipe()
    process = subprocess.Popen(
        command,
        stdout=w,
        stderr=subprocess.STDOUT)
    iothread = threading.Thread(
        target=simple_io_thread,
        args=(os.fdopen(r), queue))
    iothread.daemon=True
    iothread.start()
    
    os.close(w)