用烧瓶调用python脚本:最好的方法是什么?

时间:2017-10-16 08:05:56

标签: python matplotlib plot flask

我相当新闻,因此我对我的代码背后的逻辑以及我的思维过程是否合理有疑问。

我有一个旧的python脚本,需要大量数据,处理它然后用matplotlib生成一个图。这很好。

现在我想构建一个Web应用程序,用户选择特定的输入参数,单击提交按钮,我的服务器检查(在sqlite的帮助下)是否已经存在一个情节/数据来制作这些情节参数,如果是,则由用户下载。

如果这个图/数据不存在,我的烧瓶应用程序将调用我的python脚本,它的新情节/数据将被创建,上传到sqlite,然后用户可以从Web应用程序下载它。

正如你在我的代码中看到的那样,到目前为止,python脚本是一个外部脚本,我的计划是不在我的视图中将它包含在我的视图中,这是否有意义?我应该在这里调用外部脚本还是直接将代码复制到我的视图中? (到目前为止我想避免使用它,因为它是一个非常大的脚本)

到目前为止我的逻辑看起来像这样:

# this part works well so far, I get the user input here and redirect it to the specific page
@app.route('/plot', methods = ['GET','POST'])
def get_plot():
    if request.method == 'POST':
        input1 = request.form['input1']
        input2 = request.form['input2']
        input3 = request.form['input3']
        return redirect('plot/{}/{}/{}/'.format(input1, input2, input3))
    else:
        return render_template('plot.html')

# here it get's a bit tricky for me
@app.route('/plot/<input1>/<input2>/<input3>/')
def create_plot(input1='1', input2='2', input3='3'):
    try:
        db = get_db(DB_PLOT)
        cur = db.execute('SELECT * FROM {} WHERE param1 = {} AND param2={}'.format(input1, input2, input3)) # get all the data from the table
    except:
        return "Plot not found !"
        # CALL THE EXTERNAL PYTHON SCRIPT HERE?
        cur = db.execute('SELECT * FROM {} WHERE param1 = {} AND param2={}'.format(input1, input2, input3)) # python script should have updated the database, so i can call the data here

    data = cur.fetchall()
    return render_template('show_plot.html', data=data)

此外,我有另一个问题: 正如我所说的那样,我迄今为止只使用过它的python脚本,接受原始数据,操纵它然后用matplotlib创建一个图。 当我想在我的Web应用程序中实现它时,我是否仍然使用python脚本创建绘图,将绘图上传到sqlite然后使用Web应用程序从sqlite获取图像或者我应该只上传被操纵的数据,然后下载此来自sqlite的数据并用烧瓶创建图?

最后,我想让用户可以将图表下载为.jpg和.pdf文件。

非常感谢你!

1 个答案:

答案 0 :(得分:2)

您可以使用subprocess模块来实现此目的。根据脚本生成绘图所需的时间,您应该考虑将页面返回给用户,要求他在一段时间后刷新页面,直到绘图可用(您还可以使用javascript自动刷新)。一个耗时太长的视图函数可能会成为问题,因为Flask用于处理请求的线程数量有限,如果有太多用户同时生成图表,这可能会使您的应用程序无法使用。

在调用脚本之前返回显然不会起作用。

return "Plot not found !"
# CALL THE EXTERNAL PYTHON SCRIPT HERE?

您还需要在开始处理绘图生成之前在数据库中插入一个条目,这样其他任何用户都无法使用相同的参数再次运行您的脚本。

您的except案例(当情节不是数据库已经存在时)会看起来像(可能对SQL注入有害)

# write entry to the database with parameters but without plot
db.execute('INSERT INTO {} (param1, param2, param3) VALUES ({}, {}, {})'.format(table_name, input1, input2, input3))
# start process which does it's calculations in another process and
# updates the table we just inserted with the plot when finished
p = Popen(['/path/to/script.py', input1, input2, input3], stdin=None, stdout=None, stderr=None, close_fds=True)

return "Plot is beeing generated ..., please refresh page until the plot is available"

生成绘图的脚本将更新条目,如下所示(可能对SQL注入有害)

db.execute('UPDATE {} SET plot_blob = {} WHERE param1 = {} AND param2 = {} AND param3 = {}'.format(table_name, binary_image_data, input1, input2, input3))

注意:

  1. 您可以使用可能更整洁的url_for构建网址:

    return redirect(url_for('create_plot', input1=input1, input2=input2, input3=input3))
    
  2. 您的SQL查询可能容易受SQL injection攻击,尽管您使用的库可能会处理此问题。我不知道它是什么。

相关问题