2017-10-16 7 views
0

私はフラスコにはかなり新しいです。したがって、私のコードの背後にあるロジックと、私の思考プロセスが理にかなっているかどうかという質問があります。フラスコでpythonスクリプトを呼び出します。どのような方法が最適ですか?

私は古いpythonスクリプトを持っています。これは大量のデータを処理し、それを処理してmatplotlibでプロットを生成します。これは正常に動作します。

私は、ユーザが特定の入力パラメータを選択し、送信ボタンをクリックして、私のサーバが(もしsqliteの助けを借りて)既にプロットが存在するならば/プロットを作るデータをチェックするそれらのパラメータがあれば、それをユーザがダウンロード可能にする。

私のフラスコのアプリケーションが私のpythonスクリプトを呼び出し、そのための新しいプロット/データが作成され、sqliteにアップロードされ、ユーザーはWebアプリケーションからダウンロードできます。

私のコードではPythonスクリプトは外部のものですが、私の計画はフラスコのアプリからの私の見解には含まれていませんが、これは意味がありますか?ここで外部スクリプトを呼び出すか、コードを直接私のビューにコピーするか?

マイロジックを(私はそれが非常に大きなスクリプトですので、これまでのところ、それを避けたかった)、これまでのようになります。 としては、私のPythonスクリプトは言った、I:さらに

# 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) 

、私は別の質問を持っています今までこれまでに使ったことのない、生データを取り込み、それを操作して、matplotlibでプロットを作成します。 Webアプリケーションで実装したい場合は、まだpythonスクリプトでプロットを作成し、プロットをsqliteにアップロードしてから、Webアプリケーションでsqliteから画像を取得するか、操作したデータをアップロードしてからダウンロードしますかこのデータはsqliteから取得し、フラスコでプロットを作成しますか?

最後に、ユーザーが.jpgと.pdfファイルとしてプロットをダウンロードできるようにします。

ありがとうございました!

+0

** SQLインジェクションが可能です。文字列書式を使用してSQLクエリを作成しないでください。パラメータ化されたクエリを使用する。** – davidism

答えて

2

これを実現するには、subprocessモジュールを使用できます。スクリプトがプロットを生成するのにかかる時間に応じて、プロットが利用可能になるまでしばらくしてからページをリフレッシュするように要求するページをユーザーに返すことを検討する必要があります(頻繁にjavascriptを使用して自動リフレッシュすることもできます)。 Flaskが要求を処理するために使用するスレッドの量が限られているため、表示機能が長すぎると問題が発生することがあります。同時に多くのユーザーが同時にプロットを生成している場合、アプリケーションを使用できなくなる可能性があります。

スクリプトを呼び出す前に戻ることは明らかに機能しません。

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

はまた、他のユーザーが同じパラメータで再びあなたのスクリプトを実行することはできませんので、プロットの生成に作業を開始する前に、データベース内のエントリを挿入する必要があります。

あなたexcept場合(プロットはすでにデータベースでない場合)(SQLインジェクションにおそらくvulerable)こののようになります。

# 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インジェクションにおそらくvulerable)を次のように:

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

注:

  1. あなたは滑らかな印象かもしれませんurl_forとURL構築することができます:ライブラリあなたが使用しては、これを処理するかもしれませんがあなたのSQLクエリは、おそらくSQL injectionに対して脆弱である

    return redirect(url_for('create_plot', input1=input1, input2=input2, input3=input3)) 
    
  2. を。私はそれがどれか分かりません。

関連する問題