Django子进程实时/无缓冲输出批处理脚本的标准输出

2 投票
1 回答
1477 浏览
提问于 2025-04-16 07:19

简单来说,我为一个客户做了一些Python脚本,用来处理他们的操作数据库和电商网站数据库之间的批量导入和导出。这些脚本运行得很好,它们会把运行状态输出到标准输出(stdout),让用户知道批处理的进展。

我现在想要建立一个框架,让这些脚本可以通过Django的视图来运行,并把标准输出的内容显示在网页上,方便用户查看这些批处理的进度。

我的计划是: - 将批处理脚本作为一个子进程调用,然后把标准输出和错误输出(stderr)保存到一个文件里。 - 返回一个重定向到一个显示页面,这个页面每2秒刷新一次,逐行显示保存的文件内容。

但是问题是,标准输出和错误输出的文件在整个批处理脚本运行完或者出错之前,实际上并不会写入任何内容。

我尝试了很多方法,但都没有成功。

这是目前的视图代码。

def long_running(app, filename):
    """where app is ['command', 'arg1', 'arg2'] and filename is the file used for output"""
    # where to write the result (something like /tmp/some-unique-id)
    fullname = temppath+filename
    f = file(fullname, "a+")
    # launch the script which outputs something slowly
    subprocess.Popen(app, stdout=f, stderr=f)# .communicate()
    # once the script is done, close the output
    f.close()

def attributeexport(request):
    filename = "%d_attribute" %(int(time.time())) #set the filename to be the current time stamp plus an identifier
    app = ['python','/home/windsor/django/applications/attribute_exports.py']
    #break thread for processing.
    threading.Thread(target=long_running, args=(app,filename)).start()
    return HttpResponseRedirect('/scripts/dynamic/'+filename+'/')
    pass

def dynamic(request, viewfile):
    fileobj = open(temppath+viewfile, 'r')
    results = []
    for line in fileobj:
        results.append(line)
        if '~END' in line:
            #if the process has completed
            return render_to_response('scripts/static.html', {'displaylist':results, 'filename':viewfile})
    return render_to_response('scripts/dynamic.html', {'displaylist':results, 'filename':viewfile})
pass

1 个回答

2

使用以下内容会有帮助:

['python','-u','path/to/python/script.py']

撰写回答