0

boost::python モジュールからプロセスを実行している間、コンソールを使い続けるにはどうすればよいですか? スレッドを使用する必要があると考えましたが、何かが足りないと思います。

import pk #my boost::python module from c++
import threading
t = threading.Thread(target=pk.showExample, args=())
t.start() 

これにより、3D コンテンツをレンダリングする Window を実行する showExample が実行されます。このウィンドウが実行されている間、Python コンソールでコーディングを続けたいと思います。上記の例は、ウィンドウを表示するために機能しますが、コンソールをインタラクティブに保つことができません。それを行う方法はありますか?提案をありがとう。

こんにちはクリス

編集: showExample() C++ コードでスレッドを作成しようとしましたが、うまくいきませんでした。おそらくコンソールをスレッドにする必要がありますが、方法がわからず、役立つ例が見つかりません。

Edit2: 例をより単純にするために、これらの C++ メソッドを実装しました。

void Example::simpleWindow()
{
    int running = GL_TRUE;
    glfwInit();
    glfwOpenWindow(800,600, 8,8,8,8,24,8, GLFW_WINDOW);
    glewExperimental = GL_TRUE;
    glewInit();
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    while(running)
    {
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glfwSwapBuffers();
        running = !glfwGetKey(GLFW_KEY_ESC) && gkfwGetWindowParam(GLFW_OPENED);
    }
}

void Example::makeWindowThread()
{
    boost::thread t(simpleWindow);
    t.join();
}

役に立たないコード行があるかもしれません (実際に使用したいメソッドの一部をコピペしただけです)。どちらのメソッドも静的です。スレッドでインタラクティブ コンソールを起動し、python で pk.makeWindowThread() を起動すると、入力できなくなります。pk.makeWindowThread() の呼び出しを Python スレッドにも配置すると機能しません。(ウィンドウを表示しながらコンソールに何かを印刷しようとしています。

4

2 に答える 2

3

コンソールをインタラクティブに保ちながらプロセスを実行しようとする場合は、subprocessまたはmultiprocessingモジュールの使用を検討してください。Boost.Python 内でこれを行う場合、おそらくexecv()関数ファミリーを使用して C++ でプロセスを実行する方が適切です。

コンソールをインタラクティブに保ちながらスレッドを生成しようとする場合、 Global Interpreter Lock (GIL)を考慮する必要があります。つまり、GIL はインタープリターの周りのミューテックスであり、Python オブジェクトで実行される並列操作を防ぎます。したがって、任意の時点で、最大 1 つのスレッド (GIL を取得したスレッド) が Python オブジェクトに対する操作を実行できます。

C または C++ スレッドのないマルチスレッド Python プログラムの場合、CPython インタープリターは協調スケジューラとして機能し、同時実行を可能にします。スレッドがブロッキング呼び出しを実行しようとしていることを Python が認識すると、スレッドは制御を譲ります。たとえば、スレッドは 内で GIL を解放しますtime.sleep()。さらに、インタープリターは、特定の基準が満たされた後、スレッドに強制的に制御を譲ります。たとえば、スレッドが一定量のバイトコード操作を実行した後、インタープリターは強制的に制御を譲り、他のスレッドが実行できるようにします。

C または C++ スレッドは、Python ドキュメントではエイリアン スレッドと呼ばれることがあります。Python インタープリターには、GIL を解放してエイリアン スレッドに強制的に制御を渡す機能はありません。したがって、エイリアン スレッドは、GIL を管理して、Python スレッドとの同時実行または並列実行を許可する責任があります。これを念頭に置いて、C++ コードのいくつかを調べてみましょう。

void Example::makeWindowThread()
{
  boost::thread t(simpleWindow);
  t.join();
}

これによりスレッドが生成され、スレッドが実行を完了するthread::join()のを待ってブロックされます。tこの関数が Boost.Python を介して Python に公開されている場合、呼び出しスレッドはブロックされます。任意の時点で実行できる Python スレッドは 1 つだけであるため、呼び出し元のスレッドが GIL を所有します。呼び出し元のスレッドが でブロックさt.join()れると、インタプリタはスレッドに制御を明け渡すことができないため、他のすべての Python スレッドはブロックされたままになります。他の Python スレッドを実行できるようにするには、GIL を結合前に解放し、結合後に取得する必要があります。

void Example::makeWindowThread()
{
  boost::thread t(simpleWindow);
  release GIL // allow other python threads to run.
  t.join();
  acquire GIL // execution is going to occur within the interpreter.
}

ただし、これにより、スレッドの実行が完了するまでコンソールがブロックされます。代わりに、スレッドを生成し、 を介してスレッドから切り離すことを検討してthread::detach()ください。呼び出し元のスレッドがブロックされなくなるため、内部で GIL を管理するExample::makeWindowThread必要がなくなります。

void Example::makeWindowThread()
{
  boost::thread(simpleWindow).detach();
}

GIL の管理の詳細/例については、基本的な実装の概要についてはこの回答を読んでください。また、考慮する必要がある考慮事項をより深く掘り下げるには、この回答を読んでください。

于 2013-07-17T14:50:05.537 に答える
2

次の 2 つのオプションがあります。

  • フラグを付けて Python を開始-iします。これにより、メイン スレッドから終了するのではなく、対話型インタプリタにドロップされます。
  • インタラクティブ セッションを手動で開始します。

    import code
    code.interact()
    

    一部のライブラリ (PyQt/PySide など) は、メイン スレッドから開始しないと好まないため、2 番目のオプションは、対話型セッションを独自のスレッドで実行する場合に特に役立ちます。

    from code import interact
    from threading import Thread
    Thread(target=interact, kwargs={'local': globals()}).start()
    ...  # start some mainloop which will block the main thread
    

    local=globals()モジュールのスコープにアクセスするには、に渡すinteract必要があります。そうしないと、インタープリター セッションはスレッドのスコープのコンテンツにしかアクセスできません。

于 2013-06-28T11:24:17.247 に答える