Piszę skrypt w języku Python, używając pycurl
do konsumpcji Twitter's Sreaming API. Oto krótki fragment, który robi dokładnie to, że (wystarczy umieścić swoją Twitter login/hasło, aby go przetestować):Jak ładnie obsługiwać KeyboardInterrupt (Ctrl-c) z 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()
Problemem jest to, że ponieważ skrypt pobiera strumień, conn.perform()
nigdy nie powraca (lub bardzo rzadko). Dlatego czasami muszę przerwać skrypt, a KeyboardInterrupt
zostanie przechwycony przez metodę perform()
.
Jednak nie obsługuje go dobrze, drukuje brzydki błąd i podnosi inny wyjątek.
^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)')
cURL FAQ mówi, że aby przerwać trwającą transferu, jedną z funkcji zwrotnych (w moim przypadku handleData
) powinny zwrócić szczególną wartość. To świetnie, ale KeyboardInterrupt
nie jest przechwytywany przez żadną z funkcji wywołania zwrotnego!
Jak mogę to zrobić starannie?
EDIT: Wiem, że można złapać wyjątki, ale pycurl nadal robi śmieszne rzeczy:
Jeśli zrobić:
try:
conn.perform()
except BaseException as e:
print('We caught the exception')
print(type(e))
uzyskać:
^CTraceback (most recent call last):
File "test.py", line 6, in handleData
def handleData(data):
KeyboardInterrupt
We caught the exception
<class 'pycurl.error'>
Oznacza to, że wewnętrznie, pycurl
robi jakiś chwyt, drukuje brzydki komunikat o błędzie, a następnie podnosi pycurl.error
.
'KeyboardInterrupt' [nie jest podklasą' Exception', to podklasa 'BaseException'] (http://docs.python.org/library/exceptions.html#exception-hierarchy) - nie zmienia to jednak danych wyjściowych. (Chociaż jest to kolejny przykład, dlaczego łapanie 'Wyjątku' jest złym pomysłem.) –
Dzięki za wskazanie tego, poprawiłem mój przykład. Nie zmienia to jednak mojego pytania. – Wookai
Potrzebujesz conn.close() po conn.perform(). –