2013-02-05 17 views
7

Używam jakiejś obliczeniowej ciężkiej symulacji w (pytaniach) opartych na C rozszerzeniach Pythona opartych na C. Czasami coś jest nie tak i chciałbym zakończyć symulację. Jednakże, Ctrl-C nie wydaje się mieć żadnego efektu (poza wydrukowaniem na ekran ^C, więc muszę zabić proces przy użyciu kill lub monitora systemu.)Umożliwianie Ctrl-C przerywania pythonowego rozszerzenia C

O ile widzę pytona tylko czeka na C przedłużenie do końca i naprawdę nie komunikować się z nim w tym czasie.

Czy istnieje sposób, aby to działało?

+0

Zobacz http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python – user1929959

+0

related: [CTRL + C nie przerywa zadzwonić do wspólne -library za pomocą CTYPES w Pythonie] (http://stackoverflow.com/q/14271697/4279) – jfs

Odpowiedz

2

chciałbym przeprojektować rozszerzeń C tak, że one nie działają przez dłuższy okres

Podzielmy je więc na bardziej elementarne kroki (każdy z nich działa przez krótki czas, np. 10 do 50 milisekund) i mają te bardziej podstawowe kroki wywoływane przez kod Pythona.

continuation passing style może być istotne, aby zrozumieć, jak stylu programowania ...

+3

Niestety, nie ma w ogóle opcji w tym przypadku :) Jest to bardzo ważna symulacja z ogromną liczbą kroków i szybkości. Współpraca z pytonem na każdym etapie (lub nawet w regularnych odstępach czasu) zrujnowałaby wydajność. –

+0

Postaraj się zebrać kroki w coś trwającego kilka milisekund. Wtedy napływ do Pythona jest znikomy ... –

+0

Z pewnością warto o tym pomyśleć, ale powoduje to wiele problemów z zarządzaniem pamięcią itp. Dzięki! –

6

Python ma obsługi sygnału zainstalowanego na SIGINT który po prostu ustawia flagę, która jest sprawdzana przez główną pętlę interpretera. Aby ten program obsługi działał poprawnie, interpreter języka Python musi mieć uruchomiony kod Pythona.

Masz kilka opcji dostępnych dla Ciebie:

  1. Korzystając Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS aby zwolnić GIL wokół kodzie rozszerzenia C. Nie można używać żadnych funkcji Pythona, gdy GIL nie jest zatrzymany, ale kod Pythona (i inny kod C) może działać jednocześnie z wątkiem C (true wielowątkowość). Oddzielny wątek Pythona może być wykonywany wraz z rozszerzeniem C i przechwytywać sygnały Ctrl + C.
  2. Skonfiguruj własną procedurę obsługi SIGINT i wywołaj oryginalną procedurę obsługi sygnałów (Python). Twój operator może wtedy zrobić wszystko, co trzeba, aby anulować kod rozszerzenia C i zwrócić kontrolę do interpretera Pythona.
+0

(1) [Zwolnienie GIL zrobiłoby różnicę tylko wtedy, gdy rozszerzenie C działa w wątku tła] (http://stackoverflow.com/q/14271697/4279). (2) [wywołaj 'Py_Err_CheckSignals()' zamiast ręcznego wywoływania komunikatora Pythona] (http://stackoverflow.com/a/33652496/4279) – jfs

5

Jednak Ctrl-C wydaje się nie mieć żadnego wpływu

Ctrl-C in the shell sends SIGINT to the foreground process group. python po odebraniu sygnału ustawia flagę w kodzie C. Jeśli twoje rozszerzenie C działa w głównym wątku, to nie zostanie uruchomiona obsługa sygnału Python (i dlatego nie zobaczysz wyjątku KeyboardInterrupt w przypadku Ctrl-C), chyba że zadzwonisz pod numer PyErr_CheckSignals(), który sprawdzi flagę (oznacza to, że nie powinno spowalniać) i jeśli to konieczne, uruchamia obsługę sygnałów Pythona lub jeśli twoja symulacja pozwala na wykonanie kodu Pythona (np. jeśli symulacja używa wywołań Pythona). Jeśli rozszerzenie działa w wątku tła, wystarczy zwolnić GIL (aby umożliwić uruchamianie kodu Pythona w wątku głównym, który umożliwia uruchamianie procedur obsługi sygnału).

pokrewne: Cython, Python and KeybordInterrupt ingored

Powiązane problemy