2016-12-17 9 views
0

ローカルコマンドを非同期的にコルーチンとして実行するTornado Webアプリケーションを作成しようとしています。これは、除外されたサンプルコードです。竜巻RequestHandlerからasyncio.subprocess.Processを実行

​​

/path/to/my/script.pyが直接呼び出されると、期待通りに実行されます。また、TestHandler.getを通常の同期メソッド(run_syncを参照)として実装すると、正しく実行されます。上記のアプリを実行していると/testを呼び出すときしかし、ログを示しています

DEBUG:asyncio:Using selector: EpollSelector 
DEBUG:asyncio:execute program 'python3' stdout=stderr=<pipe> 
DEBUG:asyncio:process 'python3' created: pid 21835 

しかし、psは、プロセスが絞首刑にすることを示しています

$ ps -ef | grep 21835 
berislav 21835 21834 0 19:19 pts/2 00:00:00 [python3] <defunct> 

私は右を実装していないよ感じていますループ、または私は間違っているんだけど、examples私が見たところでは、asyncio.get_event_loop().run_until_complete(your_coro())の使い方を見ていて、asyncioとTornadoを組み合わせることはほとんどできませんでした。すべての提案は歓迎!

答えて

2

サブプロセスがサブハンドラSIGCHLDハンドラのためにトリッキーです。 asyncioでは、これは "main"イベントループでのみ動作することを意味します。 tornado.ioloop.IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop')tornado.platform.asyncio.AsyncIOMainLoop().install()に変更すると、この例は機能します。他にもいくつかのクリーンアップが必要でした。ここでは、完全なコードがあります:

#! /usr/bin/env python3 

import shlex 
import asyncio 
import logging 

import tornado.platform.asyncio 
from tornado.web import Application, url, RequestHandler 
from tornado.httpserver import HTTPServer 
from tornado.ioloop import IOLoop 

logging.getLogger('asyncio').setLevel(logging.DEBUG) 

async def run(): 
    command = "python3 /path/to/my/script.py" 
    logging.debug('Calling command: {}'.format(command)) 
    process = await asyncio.create_subprocess_exec(
     *shlex.split(command), 
     stdout=asyncio.subprocess.PIPE, 
     stderr=asyncio.subprocess.STDOUT 
    ) 
    logging.debug(' - process created') 

    result = await process.wait() 
    stdout, stderr = await process.communicate() 
    output = stdout.decode() 
    return output 

tornado.platform.asyncio.AsyncIOMainLoop().install() 
IOLoop.instance().run_sync(run) 

またその竜巻に注意してくださいはtornado.process.Subprocessで、独自のサブプロセス・インタフェースを持っているので、それはあなたがasyncio必要な唯一のものだならば、代わりにトルネードのバージョンを使用することを検討してください。同じプロセスでTornadoとasyncioのサブプロセスインターフェイスを組み合わせると、SIGCHLDハンドラと競合する可能性があるので、どちらか一方を選択するか、SIGCHLDハンドラが不要なようにライブラリを使用する必要があります(たとえば、プロセスの終了ステータスではなくstdout/stderrにあります)。

+0

こんにちはベン、答えをありがとう!あなたは答えが1つではなく、2つの方向に向いていると指摘しました。両方とも 'AsyncIOMainLoop'を使用しています(asyncio.get_event_loop()。close()を使用して明示的に閉じておく必要があります)もう一方はTornadoの 'Subprocess'です。これは私が気づいていなかったのでもう少し探検する必要があります。後者のドキュメントはそれほど完全ではありません。私の理解は 'stdin' /' stdout'オプションの 'STREAM'オプションを使ってサブプロセスと通信することが可能であるということです、それは正しいのですか? –

+0

はい、ストリームオプションを使用してサブプロセスと通信します。 –

関連する問題