3

我正在编写一个 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

显然,这种方法效率极低。什么是启动过滤器子进程并在需要时通过标准输入/标准输出与其通信的有效方法?

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

谢谢!

4

2 回答 2

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 进程返回。应该很容易适应 detex(主要是正确处理冲洗,这样一端就不会等待另一端)。

那是沟通的部分。至于“在 Django 中长期运行”可能不是一个好主意。队列可能确实太多了。

像 Celery 等人这样的任务队列是用于独立处理的任务,而不是用于处理每个任务的相同长时间运行的服务。

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

于 2012-08-07T05:04:37.053 回答
1

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

另外,我很担心缓存。假设您确实让filter程序在后台运行,读取和写入命名管道或其他任何东西。你如何确保你推动的每一根弦都立即出来?您将如何刷新管道以使输出与输入同步?

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

于 2012-08-06T19:15:45.310 回答