2017-08-31 17 views
5

Aktualnie przesyłam projekt Pythona z systemu Linux do systemu Windows (przy użyciu Anaconda Python 3.6). Wszystko działa idealnie, po prostu nie mogę uzyskać wdzięcznego wyjścia z pętli asyncio.pętla asyncio add_signal_handler() w systemie Windows

W Linuksie robię co następuje:

class GracefulExit(SystemExit): 
    code = 1 

def raise_graceful_exit(): 
    raise GracefulExit() 

loop = asyncio.get_event_loop() 
loop.add_signal_handler(signal.SIGINT, raise_graceful_exit) 
loop.add_signal_handler(signal.SIGTERM, raise_graceful_exit) 

try: 
    loop.run_forever() 
except GracefulExit: 
    pass 

shutdown() 

W Windows, niestety dostaję NotImplementedError na add_signal_handler. Bez tego oczywiście nigdy nie dostanę szansy na czyste zamknięcie programu.

Wszelkie pomysły na rozwiązanie tego problemu? Dzięki.

+0

Patrz [wydanie 23057] (http://bugs.python.org/issue23057). – eryksun

Odpowiedz

3

Windows nie ma sygnałów.

Jeśli proces zostanie zabity za pośrednictwem interfejsu API TerminateProcess, nie otrzymasz żadnej szansy na oczyszczenie (to jak "kill -9", odsuwa twój proces).

Ale okna mają dwa sposoby sygnalizowania, czy kod powinien zostać zamknięty, jeden dla programów konsolowych (np. Python.exe) i jeden dla programów GUI (pythonw.exe).

Python automatycznie obsługuje konsolę i podnosi wyjątek KeyboardInterrupt, ale możesz podpiąć własny kod do tego handler'a za pomocą interfejsów API kontrolera konsoli (https://docs.microsoft.com/en-us/windows/console/console-control-handlers), ale to prawdopodobnie przesada. Po prostu ustaw odpowiednią procedurę obsługi wyjątków w pętli zdarzeń.

W przypadku procesów GUI, system Windows wysyła komunikaty systemu Windows, takie jak WM_QUIT lub różne inne, jeśli użytkownik się wyloguje, system przechodzi w tryb oszczędzania energii itd., Możesz też obsługiwać te, za pomocą ctypów lub pakietu win32, lub dowolną z wielu bibliotek Pythona.

+0

Dzięki. Tego się bałem. Domyślam się, że najprościej byłoby dodać prosty GUI tylko dla Windows ... –

+1

@The_Fallen, czy wypróbowałeś sugestię w numerze 23057, aby dodać okresowe zadanie? @schlenk, środowisko wykonawcze C ma konsolową procedurę kontroli, która podnosi 'SIGINT' dla Ctrl + C i' SIGBREAK' dla innych zdarzeń. "KeyboardInterrupt" pochodzi z domyślnego programu obsługi Pythona, ale można go zastąpić. Dla asyncio zmieniono 'signal.set_wakeup_fd' na obsługę gniazd w systemie Windows, ale z jakiegoś powodu łatka do implementacji obsługi sygnału w pętli zdarzeń Windows nigdy nie została sfinalizowana i scalona. Nie używam asyncio, więc nie miałem powodu, by podnosić płaszcz. – eryksun

+0

Nie, nie zrobiłem, teraz dodaję tylko proste okno używające pyqt. Działa jak urok, a pętla kończy się ładnie po zamknięciu okna. Ale i tak dzięki. –