在Python中与unix过滤器进程通信

时间:2012-08-06 16:07:42

标签: python django ipc subprocess

我正在编写一个Python程序,需要使用外部unix程序清理许多小字符串,该程序用作过滤器。目前,我为每个要清理的字符串创建一个新的子进程:

import subprocess
def cleanstring(s):
    proc = subprocess.Popen(['/bin/filter','-n'],
        stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    out, err = proc.communicate(s)
    assert not err
    return out

显然,这种方法效率极低。什么是启动过滤器子进程并通过stdin / stdout与它进行通信的有效方法?

我一直在考虑使用Python Queues来实现这一点,但它们可能对此有些过分。代码将从非线程Web服务器上的Django视图调用,因此它只是一个多次调用它的线程。

谢谢!

2 个答案:

答案 0 :(得分:2)

如果你没有测量它,那么它不是性能问题,更不是“非常低效”。

也就是说,您可以与这样的子流程进行通信:

import subprocess
import sys

p = subprocess.Popen('bc', shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

 for i in range(10):
     p.stdin.write('%s*2\n' % (i,))
     res = p.stdout.readline()
     if res:
         print "vtrip says %s*2 is %s" % (i, res.strip())
         p.stdin.flush()

这将打印0-9的双精度数,由同一个bc进程返回。应该很容易适应检测(主要的是要正确处理冲洗,这样一端不会卡住等待另一端)。

这是沟通的一部分。至于“漫长的Django内部”可能不是一个好主意。队列可能确实太多了。

像Celery等人的任务队列可以独立处理任务,而不是处理每个任务的长期服务。

也许在旁边运行一些小的python守护进程,保持过滤器进程打开并处理来自Django的请求?我们是在谈论重负荷,还是在内部,例如每天100个用户?除了一些原始锁定之外,你可能不需要太多的同步。

答案 1 :(得分:1)

我认为您当前的代码是最佳解决方案。在Linux下,启动一个进程并不是那么昂贵,而且你已经整齐地封装了这个问题。并且您正在直接启动filter程序,因此您没有启动shell来运行它的开销。

另外,我更担心缓存。假设您确实在后台运行filter程序,读取和编写命名管道或其他任何东西。你怎么能确定你推出的每根弦都会立刻出来?如何刷新管道以使输出与输入同步?

您是否测量过Django服务器上的负载并发现这是一个问题?如果您已经测量了性能,请分享数字。如果你确实遇到问题,我会感到惊讶。