我正在编写一个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视图调用,因此它只是一个多次调用它的线程。
谢谢!
答案 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服务器上的负载并发现这是一个问题?如果您已经测量了性能,请分享数字。如果你确实遇到问题,我会感到惊讶。