1

組み込みのpythonで苦労しています。

DLL を実行していますが、特定の関数が呼び出されるたびに Python スクリプトを実行したいと考えています。Initialize/Finalize の呼び出しに約 75 ミリ秒の時間がかかるため、関数の最後で Py_Finalize() を呼び出すことは避けたいのですが、それを行う余裕はありません。

問題は、エラーなしで同じ .py ファイルを複数回実行できないように見えることです。

...
runResult = PyRun_SimpleFile(pyfileptr, pyfilename);
if (runResult)
{
    if (!PyErr_Occurred())
        return -4;
    PyErr_Print();
    return -3;
}
...

私はいつも-4を2回目に返すことになります。ドキュメントには、例外があった場合は PyRun_SimpleFile が -1 を返し、それ以外の場合は 0 を返すと記載されているため、それがどのように可能かさえわかりませんが、PyErr_Occurred() は例外がない場合は NULL を返します。

私が実行しているPythonファイルが単純な場合でも

print("hi")

最終的には同じ結果になります。これは、スクリプト自体によって生成された例外ではないと確信しています。

更新: スタンドアロン アプリケーションで同じコードを実行しても問題が表示されないため、これは DLL 関連の問題であることがますます明らかになっています。それでもかなり困惑しています。

4

1 に答える 1

1

OPはこちら。私は基本的に2つの質問を投げかけましたが、今ではやや貧弱な答えを持っています:

再初期化せずに Python ファイルを実行するにはどうすればよいですか? PyRun_SimpleFile() または boost::python::exec_file() をもう一度呼び出す前に finalize を呼び出さないでください。

PyRun_SimpleFile() がゼロ以外を返した後、PyErr_Occurred() が 0 を返すのはなぜですか? 簡単な答えは、まだわかりませんが、DLL の実装と、いくつかのハングまたは欠落した参照に関連しているというのが私の推測です。

私は kichik の提案に基づいて boost::python を使用しました。ベース C API よりもはるかに使いやすいとは言えませんが、読みやすいです。エラーの欠落の問題も発生しなかったため、最終的には問題が解決しました。DLL であっても、2 回連続して exec_file() を問題なく呼び出すことができました。

必要な方法で使用された boost::python の例を見つけるのに苦労したので、ここに私のコードを載せます。もちろん、これのいくつかは私のプロジェクトに固有のものですが、それでも一般的な例として価値があるかもしれません.

extern "C" LTPYTHON_API int ltPythonAnalyzeLog(char * analyzerfile, char * logfile, double timeWindow, int * results)
{

std::vector<int> countsVector;
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
    // Example of adding a variable to the global namespace
main_namespace["scriptIsRunningThroughDll"] = boost::python::long_(1);

// Load arguments for the analyzer call
{
    int argc = 3;
    wchar_t * argv[3];

    //*... assemble wchar arguments for py script ... *

    PySys_SetArgv(argc, argv);
}

int startClock = clock();
try
{
    exec_file(analyzerfile, main_namespace);
}
catch(error_already_set const &)
{
            //*... some error handling ...*

    PyObject *ptype, *pvalue, *ptraceback;
    PyErr_Fetch(&ptype, &pvalue, &ptraceback);

    handle<> hType(ptype);
    object extype(hType);
    handle<> hTraceback(ptraceback);
    object traceback(hTraceback);

    //Extract error message
    std::string strErrorMessage = extract<std::string>(pvalue);
    long lineno = extract<long> (traceback.attr("tb_lineno"));

    FILE * outfile = fopen("ltpython-error.txt", "a");
    fprintf(outfile, "%d: %s\n", lineno, strErrorMessage);
    fflush(outfile);
    fclose(outfile);

    return -1;
}

    //*... grabbing a matrix of results that were created in the script ...*
object counts = main_namespace["sortedIndicationCounts"];
list countsList = extract<list>(counts);
int totalCount = 0;
for (int i = 0; i < len(countsList); i++)
{
    list singleCount = extract<list>(countsList[i]);
    countsVector.push_back(extract<int>(singleCount[1]));
    totalCount += countsVector[i];
}

    //*... returning the number of milliseconds that elapsed ...*
return clock() - startClock;
}

エラー処理はこの回答に基づいています。

于 2013-08-27T15:57:32.083 に答える