7

CSV ファイルから一部のデータを処理するための Python スクリプトを作成しました。CSV のサイズに応じて、スクリプトが完了するまでに 3 ~ 30 分かかります。

これに Web インターフェイスを追加して、どこからでも CSV データ ファイルをアップロードできるようにします。基本的な HTTP POST アップロード ページを作成し、Python の CGI モジュールを使用しましたが、しばらくするとスクリプトがタイムアウトしてしまいます。

このスクリプトは、最初に HTTP ヘッダーを出力し、CSV のすべての行を反復処理した後にデータのビットを出力します。例として、この print ステートメントは約 30 秒ごとにトリガーされます。

# at the very top, with the 'import's
print "Content-type: text/html\n\n Processing ... <br />"

# the really long loop.
for currentRecord in csvRecords:
    count = count + 1
    print "On line " + str(count) + " <br />"

ブラウザはヘッダーを受信し、少量のデータを受信し続けるため待機すると想定しました。しかし実際には、データをまったく受信せずError 504、多数の行を含む CSV を指定するとタイムアウトになるようです。

どこかでキャッシングが行われているのではないでしょうか?ログから、

[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm

これを解決する最善の方法は何ですか? または、そのようなスクリプトをブラウザーで実行するのは適切ではないでしょうか?

編集: これは私自身の使用のためのスクリプトです。通常は自分のコンピューターで使用するつもりですが、旅行中や電話などで Web ベースのインターフェイスが役立つと思いました。また、ダウンロードするものは何もありません。スクリプトは、おそらく最後にレポートを電子メールで送信します。

4

6 に答える 6

12

私は次のように作業を分けます。

  1. POST された CSV ファイルを受け入れる Web アプリの URL。Web アプリは、CSV コンテンツをデータベース テーブルなどのオフライン キューに入れます。Web アプリの応答は、キューに入れられたアイテムの一意の ID である必要があります (たとえば、自動インクリメント ID 列を使用します)。クライアントは、パート 3 のためにこの ID を保存する必要があります。

  2. 作業のためにキューをポーリングし、処理を行うスタンドアロン サービス アプリ。処理が完了したら、一意の ID をキーとして、別のデータベース テーブルに結果を格納します。

  3. 処理された結果を取得できる Web アプリの URL http://server/getresults/uniqueid/、. 処理が終了した場合 (つまり、一意の ID が結果データベース テーブルで見つかった場合)、結果を返します。終了していない場合、応答はこれを示すコードである必要があります。たとえば、カスタム HTTP ヘッダー、HTTP ステータス レスポンス、レスポンス ボディ「PENDING」などです。

于 2010-01-20T12:00:21.677 に答える
5

以前にこの状況が発生したことがあり、cronjobs を使用しました。HTTP スクリプトは、実行するジョブ (DB またはディレクトリ内のファイル) をキューに書き込むだけで、cronjob はそれを読み取り、そのジョブを実行します。

于 2010-01-20T11:52:15.567 に答える
4

stdout.flush()ページ バッファに相当するデータが書き込まれるまで、スクリプトは実際には Web サーバーに何も書き込んでいないため、おそらく.

しかし、これを解決する適切な方法は、他の人が示唆したように、別のスレッド/プロセスで処理を行い、ステータスを示す自動更新ページをユーザーに表示し、進行状況バーまたはその他の派手なビジュアルを維持することです。退屈から。

于 2010-01-20T11:59:40.803 に答える
2

Randal Schwartz のWatching long processes through CGIを参照してください。この記事では Perl を使用していますが、手法は言語に依存しません。

于 2010-01-20T12:03:14.637 に答える
2

非常によく似た質問here。長いプロセスを生成し、ajax ベースの進行状況バーをユーザーに返すことをお勧めします。このようにして、ユーザーは Web インターフェイスの贅沢を享受し、タイムアウトなしの贅沢を享受できます。

于 2010-01-20T12:06:52.507 に答える
1

最善の方法は、更新をどこかに投稿する独立したスクリプトを実行することです(フラットファイル、データベースなど...)。Python から独立したプロセスをフォークする方法がわからないため、コード例を示すことはできません。

Web サイトで進行状況を表示するには、これらのステータスの更新を読み取り、たとえば素敵な進行状況バーを表示するページに ajax 要求を実装します。

自動更新のために setTimeout("refreshProgressBar[...]) または meta-refresh のようなものを追加します。

于 2010-01-20T11:54:01.110 に答える