2012-02-07 11 views
5

私たちは小さなcサーバアプリケーションを開発しています。サーバーアプリケーションは、何らかのデータ処理を行い、クライアントに応答します。データ処理部分を構成可能かつ柔軟に保つために、私たちはスクリプト作成に移り、Pythonのために用意された様々な準備モジュールの利用可能性に基づいて、私たちはPython-C APIを使って、cとpythonの間でデータを送受信しています。Python-C APIの並行性の問題

ザ・アルゴリズムは次のように動作します: -

  1. サーバーがクライアントからいくつかのデータを受け取り、このデータは、Cで作成した辞書に格納されています。辞書はAPI関数PyDict_New()を使用して作成されます。 cから。入力は、PyDict_SetItemString()API関数を使用して辞書にキー値のペアとして格納されます。
  2. 次にPythonスクリプトPyRun_SimpleString()を実行します。スクリプトをパラメータとして渡します。このスクリプトは、cで作成した辞書を使用します。 cで作成した辞書を、PyImport_AddModule()メソッドを使用してスクリプトにアクセスできるようにします。 PyModule_AddObject();
  3. 上記で作成した同じ辞書に、データ処理の結果をキー値のペアとしてスクリプトに格納します。 cコードは、スクリプトの実行後に結果変数(キーと値のペア)に簡単にアクセスできます。

問題 我々が直面している問題は、異なるクライアントから来る同時要求の場合です。異なるクライアントから複数のリクエストが入った場合、我々は参照カウントの例外を処理する傾向があります。ユーザーに提供されるリクエストごとに、そのユーザーのみの独立した辞書を作成することに注意してください。この問題を克服するために、PyRun_SimpleString()を呼び出しました。 PyEval_AcquireLock()内; PyEval_ReleaseLock();)を実行すると、スクリプトの実行がブロッキング呼び出しになりました。したがって、スクリプトの実行に時間がかかる場合、他のすべてのユーザーも応答を待っています。

可能な限り最良の方法を提案したり、間違っている箇所を指摘してください。詳細は私にpingしてください。

ご迷惑をおかけして申し訳ありません。

答えて

1

おそらく、this answerに記載されている通話のうちの1つが欠落している可能性があります。

+0

参考までに感謝します。ちなみに、私はそれらの関数を呼び出しましたが、それでも動作しません。 – Will

1

おそらくhttp://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lockを読んでください。問題は最初の段落で説明されています。

GILを取得したら、Pythonオブジェクトを直接操作してGILを取得します。 PyRun_SimpleStringへの呼び出しは内部的にGILを処理し、長時間実行される操作またはすべてのX命令ではGILを放棄します。しかし、それは本当にマルチスレッドではありません。

編集:

あなたがロックを取得する必要があり、あなたはPythonが、それは別のスレッドの状態にあります知っていることを確認する必要があります

// acquire the lock and switch thread state 
PyEval_AcquireLock(); 
PyThreadState_Swap(perThreadState); 

// execute some python code 
PyEval_SimpleString("print 123"); 

// clear the thread state and release the lock 
PyThreadState_Swap(NULL); 
PyEval_ReleaseLock(); 
+0

こんにちはTom、答えに感謝します。あなたは真にマルチスレッドではないことを丁寧に教えてください。スクリプトは決して並行して実行できないと言っていますか? – Will

+0

グローバルインタープリタのロックがあります。スレッド数にかかわらず、一度に実行できるPythonバイトコード命令は1つだけです。ファイルのような長時間実行される関数は、実行中に一時的にロックを解放し、Pythonインタプリタは定期的にロックを放棄しますが、最終的には1つのプロセス内でPythonバイトコードが連続して実行されます。 –

+0

そのトムに感謝します。あなたの時間を感謝します。これを確認してください:PyRun_SimpleStringが2つの(あるいは多分n個の)別々の "c"スレッドで実行されている場合、GIL自体を処理するので、PyRun_SimpleStringを呼び出す前にブロックする必要はありません。 – Will

1

私はあなたがmultiprocessingモジュールを調査示唆しています。