2013-01-04 4 views
2

(토네이도 사용) 큰 데이터를 느린 클라이언트로 전송하려고하고 전송 된 데이터의 양을 인쇄한다고 가정합니다. 이 목적으로이 간단한 코드를 작성했습니다.finally tornado gen engine에서 finally 블록이 작동하지 않습니다.

from tornado import web, ioloop, gen 

class MainHandler(web.RequestHandler): 
    @web.asynchronous 
    @gen.engine 
    def get(self): 
     print '(start' 
     try: 
      for i in xrange(100): 
       self.write('*' * 100000) # write ~100KB of data 
       yield gen.Task(self.flush) # wait for reciever to recieve 
       print '- wrote', i 
     finally: 
      print '| finally' 
      self.finish() 
     print ') finish' 

application = web.Application([ 
    (r"/", MainHandler), 
    ]) 

application.listen(8888) 
ioloop.IOLoop.instance().start() 

그러나이 코드는 예상대로 작동하지 않습니다. 이 간단한 클라이언트 :

req = urlopen('http://127.0.0.1:8888/') 
sys.exit() # exit without reading response 

서버 출력한다 :

(start 
- wrote 0 
- wrote 1 
- wrote 2 
WARNING:root:Read error on 7: [Errno 104] Connection reset by peer 
WARNING:root:error on read 
Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 361, in _handle_read 
    if self._read_to_buffer() == 0: 
    File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 428, in _read_to_buffer 
    chunk = self._read_from_socket() 
    File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 409, in _read_from_socket 
    chunk = self.socket.recv(self.read_chunk_size) 
error: [Errno 104] Connection reset by peer 

하지만 어느 finallyfinish 인쇄된다.

무엇이 문제입니까?!

UPDATE : 내가 처리기에 대한 on_connection_close를 구현하는 경우 on_connection_close 콜백이 호출됩니다 것을 발견하고, 오류가 콘솔에 인쇄되지 않습니다

. 그러나이 기능은 무엇인가? (이미 빈 몸체가있는 RequestHandler에 정의되어 있습니다.)

큰 대답 : 제 발전기가 close d가 아닌 이유는 무엇입니까? 가비지 수집 여부 PEP-342는 finally 블록이 어떤 상황에서도 실행되어야한다고 말합니다. finally 조항에

+0

발전기가 더 많은 입력을 기다리는 중이라고 생각합니까? –

+0

@Martijn 신호 (또는 Control + C)를 사용하여 서버를 닫더라도 finally 블록이 실행되지 않습니다. 마침내 강제로 블록을 실행할 수 있습니까? –

+0

나는 그걸로 * 실행 *하지만, 그 시간에 의해'stdout'는 이미 닫혀 의심된다. 명시 적으로 전용 파일을 열어 보았습니까? –

답변

1

발전기는 파이썬 버전 < = 3.3 __del__을 사용하고 다른 소멸자의 모든 제한이 구현 - 그들이 참조 사이클의 존재에 신속하게 모든 경우에 실행되도록 보장되지 않습니다. 파이썬 3.4에서 이것은 향상되었고 (http://www.python.org/dev/peps/pep-0442/) 발전기의 finally 절이 훨씬 더 안정적으로 실행됩니다.