gpt4 book ai didi

python - 在 Django 中,如何调用启动时间较慢的子进程

转载 作者:太空狗 更新时间:2023-10-30 02:35:40 24 4
gpt4 key购买 nike

假设您在 Linux 上运行 Django,并且您有一个 View ,并且您希望该 View 从一个名为 cmd 的子进程返回数据,该子进程运行在 View 创建的文件上,例如:

 def call_subprocess(request):
response = HttpResponse()

with tempfile.NamedTemporaryFile("W") as f:
f.write(request.GET['data']) # i.e. some data

# cmd operates on fname and returns output
p = subprocess.Popen(["cmd", f.name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

out, err = p.communicate()

response.write(p.out) # would be text/plain...
return response

现在,假设 cmd 启动时间非常慢,但运行时间非常快,并且它本身没有守护进程模式。我想改进此 View 的响应时间。

我想通过在工作池中启动多个 cmd 实例来让整个系统运行得更快,让它们等待输入,并让 call_process 要求其中一个工作池进程处理数据。

这实际上分为两部分:

第 1 部分。调用 cmdcmd 的函数等待输入。这可以通过管道来完成,即

def _run_subcmd():
p = subprocess.Popen(["cmd", fname],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)

out, err = p.communicate()
# write 'out' to a tmp file
o = open("out.txt", "W")
o.write(out)
o.close()
p.close()
exit()

def _run_cmd(data):
f = tempfile.NamedTemporaryFile("W")
pipe = os.mkfifo(f.name)

if os.fork() == 0:
_run_subcmd(fname)
else:
f.write(data)

r = open("out.txt", "r")
out = r.read()
# read 'out' from a tmp file
return out

def call_process(request):
response = HttpResponse()

out = _run_cmd(request.GET['data'])

response.write(out) # would be text/plain...
return response

第 2 部分。一组在后台运行并等待数据的工作程序。即我们想扩展上面的内容,以便子进程已经在运行,例如当 Django 实例初始化时,或首次调用此 call_process 时,会创建一组这样的 worker

WORKER_COUNT = 6
WORKERS = []

class Worker(object):
def __init__(index):
self.tmp_file = tempfile.NamedTemporaryFile("W") # get a tmp file name
os.mkfifo(self.tmp_file.name)
self.p = subprocess.Popen(["cmd", self.tmp_file],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.index = index

def run(out_filename, data):
WORKERS[self.index] = Null # qua-mutex??
self.tmp_file.write(data)
if (os.fork() == 0): # does the child have access to self.p??
out, err = self.p.communicate()
o = open(out_filename, "w")
o.write(out)
exit()

self.p.close()
self.o.close()
self.tmp_file.close()
WORKERS[self.index] = Worker(index) # replace this one
return out_file

@classmethod
def get_worker() # get the next worker
# ... static, incrementing index

应该在某处对 worker 进行一些初始化,如下所示:

def init_workers(): # create WORKERS_COUNT workers
for i in xrange(0, WORKERS_COUNT):
tmp_file = tempfile.NamedTemporaryFile()
WORKERS.push(Worker(i))

现在,我上面的内容变成了这样:

def _run_cmd(data):
Worker.get_worker() # this needs to be atomic & lock worker at Worker.index

fifo = open(tempfile.NamedTemporaryFile("r")) # this stores output of cmd

Worker.run(fifo.name, data)
# please ignore the fact that everything will be
# appended to out.txt ... these will be tmp files, too, but named elsewhere.

out = fifo.read()
# read 'out' from a tmp file
return out


def call_process(request):
response = HttpResponse()

out = _run_cmd(request.GET['data'])

response.write(out) # would be text/plain...
return response

现在,问题:

  1. 这行得通吗? (我刚刚在 StackOverflow 中输入了这个,所以我确定存在问题,但从概念上讲,它会起作用)

  2. 要寻找的问题是什么?

  3. 是否有更好的替代方案?例如线程也能工作吗(它是 Debian Lenny Linux)?有没有像这样处理并行进程工作池的库?

  4. 我应该注意与 Django 的交互吗?

感谢阅读!我希望你和我一样觉得这是一个有趣的问题。

布莱恩

最佳答案

我似乎是在赌这个产品,因为这是我第二次回复推荐这个产品。

但您似乎需要消息队列服务,尤其是分布式消息队列。

它是如何工作的:

  1. 您的 Django 应用请求 CMD
  2. CMD 被添加到队列中
  3. CMD 被推送到多个作品
  4. 执行并向上游返回结果

大部分代码都已存在,您不必着手构建自己的系统。

看看 Celery,它最初是用 Django 构建的。

http://www.celeryq.org/ http://robertpogorzelski.com/blog/2009/09/10/rabbitmq-celery-and-django/

关于python - 在 Django 中,如何调用启动时间较慢的子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1428900/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com