如何在龙卷风中制作异步 RequestHandler python
How make an async RequestHandler in tornado python
目前我正在使用 tornado 开发我的后端网络服务器。
我现在遇到的问题:
- 当发出请求并且服务器正在处理请求时,所有其他请求都被阻止
我的请求处理程序:
class UpdateServicesRequestHandler( RequestHandler ):
@gen.coroutine
def get( self ):
update = ServiceUpdate()
response = yield update.update_all( )
if self.request.headers.get('Origin'):
self.set_header( 'Access-Control-Allow-Origin', self.request.headers.get('Origin') )
self.set_header( 'Content-Type', 'application/json')
self.write( response )
我的update_all()
:
@gen.coroutine
def update_all( self ):
for service in self.port_list:
response = yield self.update_service( str( service.get( 'port' ) ) )
self.response_list.append( response )
self.response = json.dumps( self.response_list )
return self.response
我的update_sevice()
:
process = Popen( [ command ], stdout=PIPE, stderr=PIPE, shell=True )
output, error = process.communicate()
问题是,我需要 update_all()
方法的结果。
那么有没有可能让这个请求不阻止我的整个服务器请求?
谢谢!
您需要在 subprocess.Popen
周围使用 tornado 的包装器以避免阻塞事件循环:
from tornado.process import Subprocess
from subprocess import PIPE
from tornado import gen
@gen.coroutine
def run_command(command):
process = Subprocess([command], stdout=PIPE, stderr=PIPE, shell=True)
yield process.wait_for_exit() # This waits without blocking the event loop.
out, err = process.stdout.read(), process.stderr.read()
# Do whatever you do with out and err
除了按照 dano 的建议使用 tornado.process.Subprocess
之外,您还应该使用 stdout=tornado.process.Subprocess.STREAM
而不是 PIPE
,并异步读取 stdout/stderr。使用 PIPE
将适用于少量输出,但如果您使用 PIPE
并且子进程尝试写入过多数据(以前是 4KB,但限制是在大多数现代 linux 系统中更高)。
process = Subprocess([command],
stdout=Subprocess.STREAM, stderr=Subprocess.STREAM,
shell=True)
out, err = yield [process.stdout.read_until_close(),
process.stderr.read_until_close()]
目前我正在使用 tornado 开发我的后端网络服务器。
我现在遇到的问题:
- 当发出请求并且服务器正在处理请求时,所有其他请求都被阻止
我的请求处理程序:
class UpdateServicesRequestHandler( RequestHandler ):
@gen.coroutine
def get( self ):
update = ServiceUpdate()
response = yield update.update_all( )
if self.request.headers.get('Origin'):
self.set_header( 'Access-Control-Allow-Origin', self.request.headers.get('Origin') )
self.set_header( 'Content-Type', 'application/json')
self.write( response )
我的update_all()
:
@gen.coroutine
def update_all( self ):
for service in self.port_list:
response = yield self.update_service( str( service.get( 'port' ) ) )
self.response_list.append( response )
self.response = json.dumps( self.response_list )
return self.response
我的update_sevice()
:
process = Popen( [ command ], stdout=PIPE, stderr=PIPE, shell=True )
output, error = process.communicate()
问题是,我需要 update_all()
方法的结果。
那么有没有可能让这个请求不阻止我的整个服务器请求?
谢谢!
您需要在 subprocess.Popen
周围使用 tornado 的包装器以避免阻塞事件循环:
from tornado.process import Subprocess
from subprocess import PIPE
from tornado import gen
@gen.coroutine
def run_command(command):
process = Subprocess([command], stdout=PIPE, stderr=PIPE, shell=True)
yield process.wait_for_exit() # This waits without blocking the event loop.
out, err = process.stdout.read(), process.stderr.read()
# Do whatever you do with out and err
除了按照 dano 的建议使用 tornado.process.Subprocess
之外,您还应该使用 stdout=tornado.process.Subprocess.STREAM
而不是 PIPE
,并异步读取 stdout/stderr。使用 PIPE
将适用于少量输出,但如果您使用 PIPE
并且子进程尝试写入过多数据(以前是 4KB,但限制是在大多数现代 linux 系统中更高)。
process = Subprocess([command],
stdout=Subprocess.STREAM, stderr=Subprocess.STREAM,
shell=True)
out, err = yield [process.stdout.read_until_close(),
process.stderr.read_until_close()]