【问题标题】:Check if a Specific multiprocess Process object is Running and Stop said Process with a Click of a Button in a Template?通过单击模板中的按钮检查特定的多进程进程对象是否正在运行并停止所述进程?
【发布时间】:2018-03-28 03:50:32
【问题描述】:

我可以启动一个进程并将命令行输出流式传输到模板,直到它结束并在进程运行时使用flask和jinja渲染模板:

@app.route('/tasks/<task>', methods=['GET', 'POST'])
def tasks(task):
    running_task = multiprocessing.current_process()
    if request.method == 'POST':
        if task == 'training':
            running_task = train_task(create_path(app.config['ARCHITECTURES_DIRECTORY'],
                                                   get('architecture_name') + '.json'),
                                       create_path(app.config['DATASET_DIRECTORY'],
                                                   get('dataset_name')),
                                       int(get('desired_image_size')),
                                       int(get('num_epochs')),
                                       int(get('checkpoint_epochs')),
                                       int(get('batch_size')),
                                       'charsets/chars.txt',
                                       float(get('learning_rate')),
                                       get('optimizer'),
                                       getlist('metrics'),
                                       get('loss'))
        flash(task + " has started.")
    return render_template('tasks.html', task=running_task)

def train_task(architecture_config_file,
               dataset_dir,
               desired_image_size,
               num_epochs,
               checkpoint_epochs,
               batch_size,
               charset_file,
               learning_rate,
               optimizer,
               metrics,
               loss):
    task = Process(target=train_model,
                         args=(
                             architecture_config_file,
                             dataset_dir,
                             learning_rate,
                             metrics,
                             loss,
                             optimizer,
                             desired_image_size,
                             charset_file,
                             ' ',
                             num_epochs,
                             batch_size,
                             checkpoint_epochs
                         ))
    task.start()
    return task

我将如何能够做到以下几点:

  1. 知道进程是否正在运行。
  2. 如果我不想让它完成,请终止进程。

【问题讨论】:

  • 为什么首先将它作为子进程运行?将它作为程序的一部分运行不是更好吗,因为它已经在 Python 中了?
  • 如果我不将它作为子进程运行,我将不得不在页面加载之前等待输出。我确实打算先加载页面,然后在进程运行时将输出流式传输到页面中。不幸的是,进程输出将其记录到命令行,我无法控制它。
  • 但如果它是一个 Python 进程,应该可以将其更改为不写入stdout?然后你应该能够将它作为一个线程运行,我想。但也许你不是train.py的作者?
  • 我不是 train.py 使用的库的作者。
  • 好的,这会使事情稍微复杂化,但是您始终可以在调用库函数之前重定向标准输出,然后在调用后将其重置。如果这种情况发生在很多地方,你可以使用装饰器或类似的东西来包装它。它有点复杂,但我仍然更喜欢创建一个子进程,只是为了捕获标准输出。

标签: python flask subprocess


【解决方案1】:

我设法通过在这个正在运行的进程模板中公开当前正在运行的进程的名称来解决问题。

{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block body %}
    <h3>Running Tasks</h3>
    <ul class="collection black-text">
    {% if not task %}
        <li class="collection-item">No task is running.</li>
    {% else %}
        <li class="collection-item row">
            <ul>
                <li class="col s3">{{ task }}</li>
                <li class="col s3">
                    <form method="post" action="{{ url_for('terminate', task=task) }}">
                        <button type="submit" class="waves-effect waves-light btn red">Terminate</button>
                    </form>
                </li>
            </ul>
        </li>
    {% endif %}
    </ul>
{% endblock %}
{% block extra_script %}
    <script type="text/javascript" src="{{ url_for('static', filename='js/toast.js') }}"></script>
    <script>
        toast({{ get_flashed_messages()|tojson }})
    </script>
{% endblock %}

这是终止进程的部分:

@app.route('/terminate/<task>', methods=['POST'])
def terminate(task):
    was_terminated_manually = False
    for running_task in multiprocessing.active_children():
        if running_task.name == task:
            running_task.terminate()
            running_task.join()
            was_terminated_manually = True
            flash(running_task.name + " is terminated")
            break
    if not was_terminated_manually:
        flash(task + " was already terminated.")
    return redirect(url_for('tasks', task='view'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多