4

我希望能够在 python 中生成一个进程并进行两种通信。当然,Pexpect 做到了这一点,并且确实是我可能采用的一种方式。但是,它并不十分理想。

我的理想情况是拥有一个只涉及标准 python 库的跨平台通用技术。子进程非常接近,但我必须等待进程终止才能安全地与之交互这一事实是不可取的。

查看文档,它确实说有一个我可以直接操作的标准输入、标准输出和标准错误文件描述符,但是有一个很大的警告说“不要这样做”。不幸的是,它并不完全清楚为什么存在这个警告,但从我从谷歌收集到的信息是它与操作系统缓冲有关,并且当这些内部缓冲区失败时,可以编写出意外死锁的代码(作为旁注,任何例子显示错误的方式和正确的方式将不胜感激)。

因此,冒着代码陷入潜在死锁的风险,我认为使用 poll 或 select 从正在运行的进程交互读取而不杀死它可能会很有趣。虽然我失去了(我认为)跨平台能力,但我喜欢它不需要额外的库的事实。但更重要的是,我想知道这是否是个好主意。我还没有尝试过这种方法,但我担心可能会破坏我的程序的陷阱。它可以工作吗?我应该测试什么?

在我的具体情况下,我并不真正关心能否写入进程,只是反复读取它。另外,我不希望我的进程转储大量文本,所以我希望避免死锁问题,但是我想确切地知道这些限制是什么,并能够编写一些测试来查看它在哪里发生故障。

4

4 回答 4

3

使用 Python 2.6 标准库中的多处理模块。

它有一个Queue 类,可用于读取和写入。

于 2009-07-10T21:16:58.833 回答
1

我在一个单独的线程中执行此操作,使用消息队列在线程之间进行通信。在我的情况下,子进程将 % complete 打印到标准输出。我希望主线程建立一个漂亮的进度条。

 if sys.platform == 'win32':
        self.shell = False
        self.startupinfo = subprocess.STARTUPINFO()
        self.startupinfo.dwFlags = 0x01
        self.startupinfo.wShowWindow = 0
    else:
        self.shell = True
        self.startupinfo = None

. . .

f = subprocess.Popen( cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env = env, shell = self.shell, startupinfo = self.startupinfo )
    f.stdin.close()
    line = ''
    while True:
        log.debug('reading')
        c = f.stdout.read(1)

        log.debug(c)

        if len(c) == 0:
            log.info('stdout empty; must be done')
            break;
        if ord(c) == 13:
            continue
        if c == '%':
            # post % complete message to waiting thread.
            line = ''
        else:
            line += c


    log.info('checking for errors')
    errs = f.stderr.readlines()

    if errs:
        prettyErrs = 'Reported Errors: '
        for i in errs:
            prettyErrs += i.rstrip('\n')

        log.warn( prettyErrs )
        #post errors to waiting thread
    else:
        print 'done'        
    return
于 2009-07-12T21:25:18.247 回答
0

简短的回答是,如果没有将这个概念设计到您的系统中,就没有一个好的跨平台流程管理系统。尤其是在标准库中。即使是各种 unix 版本也有其自身的兼容性问题。

您最好的选择是使用适当的事件处理来检测所有流程,以注意来自任何 IPC 系统在任何平台上运行最好的事件。命名管道将是您描述的问题的一般路径,但每个平台上都会存在实现差异。

于 2009-07-10T17:22:49.757 回答
0

原谅我对这个话题的无知,但你不能用 -u 标志启动 python 来表示“无缓冲”吗?

这可能也很有趣...... http://www.gossamer-threads.com/lists/python/python/658167

于 2009-08-18T16:28:37.200 回答