将Celery任务的子进程标准输出重定向到日志文件

3

我有一个 celery 任务,它通过 subprocess 调用 Django 应用程序外部的其他 python 脚本。这个程序中有一些 print,我希望将这些 print 记录在我的 celery 日志文件或数据库中。当我在 Django 的 settings.py 文件中设置了 CELERY_ALWAYS_EAGER = True 时,一切都正常工作。如果我不设置此选项,Celery 任务仅在子进程退出时记录标准输出(stdout)。似乎是 p.stdout.readline() 阻塞了。

run-test.py 是一个长时间运行的进程,需要几分钟,但会打印出它正在做的事情。我想捕获这个过程。

@shared_task
def run_tests(scenario_path, vu):
    basedir = os.path.abspath(os.path.dirname(__file__))
    config_path = '%s/../../scripts/config.ini' % basedir
    cmd = ['python', '%s/../../scripts/aws/run-test.py' % basedir, '%s' % config_path, scenario_path, str(vu), str(2)]
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    while True:
        line = p.stdout.readline()
        if line != '':
            logger.info(line)
        else:
            return
1个回答

0

我发现这非常有用,使用select进行轮询而不是在readline上阻塞。

https://gist.github.com/bgreenlee/1402841

child = subprocess.Popen(popenargs, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE, **kwargs)

log_level = {child.stdout: stdout_log_level,
             child.stderr: stderr_log_level}

def check_io():
    ready_to_read = select.select([child.stdout, child.stderr], [], [], 1000)[0]
    for io in ready_to_read:
        line = io.readline()
        logger.log(log_level[io], line[:-1])

# keep checking stdout/stderr until the child exits
while child.poll() is None:
    check_io()

check_io()  # check again to catch anything after the process exits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接