Estoy escribiendo un script en Python usando pycurl
consumir Twitter's Sreaming API. He aquí un breve fragmento que hace exactamente eso (en pocas palabras su nombre de usuario de Twitter/contraseña para probarlo):Cómo manejar KeyboardInterrupt (Ctrl-c) muy bien con pycurl?
import pycurl
user = 'USER'
password = 'PWD'
def handleData(data):
print(data)
conn = pycurl.Curl()
conn.setopt(pycurl.USERPWD, "%s:%s" % (user, password))
conn.setopt(pycurl.URL, 'https://stream.twitter.com/1/statuses/sample.json')
conn.setopt(pycurl.WRITEFUNCTION, handleData)
conn.perform()
El problema es que debido a que el guión consume una corriente, conn.perform()
nunca se regresa (o muy raramente). Por lo tanto, a veces necesito interrumpir el script, y el KeyboardInterrupt
es capturado por el método perform()
.
Sin embargo, no lo maneja bien, imprime un error feo y genera una excepción diferente.
^CTraceback (most recent call last):
File "test.py", line 6, in handleData
def handleData(data):
KeyboardInterrupt
Traceback (most recent call last):
File "test.py", line 12, in <module>
conn.perform()
pycurl.error: (23, 'Failed writing body (0 != 2203)')
El cURL FAQ dice que para interrumpir una transferencia en curso, una de las funciones de devolución de llamada (en mi caso handleData
) debe devolver un valor especial. ¡Esto es genial, pero el KeyboardInterrupt
no es capturado por ninguna de la función de devolución de llamada!
¿Cómo puedo hacer esto perfectamente?
EDIT: Sé que usted puede capturar las excepciones, pero pycurl sigue algunas cosas divertidas:
Si hago:
try:
conn.perform()
except BaseException as e:
print('We caught the exception')
print(type(e))
me sale:
^CTraceback (most recent call last):
File "test.py", line 6, in handleData
def handleData(data):
KeyboardInterrupt
We caught the exception
<class 'pycurl.error'>
Esto significa que internamente, pycurl
realiza algún tipo de captura, imprime un feo mensaje de error y luego levanta un pycurl.error
.
'KeyboardInterrupt' [no es una subclase de' Exception', que es una subclase de 'BaseException'] (http://docs.python.org/library/exceptions.html#exception-hierarchy); sin embargo, eso no cambia el resultado. (Aunque es otro ejemplo de por qué atrapar 'Exception' es una mala idea.) –
Gracias por señalarlo, corregí mi ejemplo. Sin embargo, no cambia mi pregunta. – Wookai
Necesita conn.close() después de conn.perform(). –