2013-02-05 12 views
7

Sto eseguendo alcune simulazioni computazionalmente pesanti in estensioni python basate su C (fatte in casa). Occasionalmente mi capita di sbagliare e vorrei terminare una simulazione. Tuttavia, Ctrl-C non sembra avere alcun effetto (oltre alla stampa di ^C sullo schermo, quindi devo interrompere il processo utilizzando kill o il monitor di sistema.Permettere a Ctrl-C di interrompere un'estensione C Python

Per quanto posso vedere Python aspetta solo il C estensione per finire e in realtà non comunica con esso durante questo periodo.

c'è un modo per fare questo lavoro?

+0

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

+0

correlati: [CTRL + C non interrompe chiamare per condiviso -library usando CTYPES in Python] (http://stackoverflow.com/q/14271697/4279) – jfs

risposta

2

vorrei ridisegnare le estensioni C in modo che non corrono per un lungo periodo

Quindi, dividerli in passaggi più elementari (ciascuno in esecuzione per un breve periodo di tempo, ad esempio Da 10 a 50 millisecondi) e hanno questi passaggi più elementari chiamati dal codice Python.

continuation passing style potrebbero essere rilevanti per comprendere, come uno stile di programmazione ...

+3

Spiacente, non un'opzione affatto in questo caso :) È una simulazione con un numero enorme di passaggi e la velocità è essenziale. Interfacciare con python ad ogni passo (o anche ad intervalli regolari) rovinerebbe l'efficienza. –

+0

Prova a raggruppare i passaggi in qualcosa che dura alcuni millisecondi. Quindi il sovraccarico di andare a Python è trascurabile ... –

+0

Vale sicuramente la pena pensarci, ma solleva un sacco di problemi con la gestione della memoria ecc. Grazie! –

6

Python ha un gestore di segnale installato su SIGINT che stabilisce semplicemente una bandiera che viene controllato dal circuito principale interprete. Perché questo gestore funzioni correttamente, l'interprete Python deve eseguire il codice Python.

di avere un paio di opzioni a vostra disposizione:

  1. Usa Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS per rilasciare il GIL attorno al codice di estensione C. Non puoi usare alcuna funzione Python quando non reggi GIL, ma il codice Python (e altro codice C) può essere eseguito contemporaneamente al tuo thread C (vero multithreading). Un thread Python separato può essere eseguito insieme all'estensione C e catturare i segnali Ctrl + C.
  2. Impostare il proprio gestore SIGINT e chiamare il gestore di segnale originale (Python). Il tuo gestore SIGINT può quindi fare tutto ciò che è necessario per cancellare il codice di estensione C e restituire il controllo all'interprete Python.
+0

(1) [il rilascio di GIL farebbe alcuna differenza solo se l'estensione C viene eseguita in un thread in background] (http://stackoverflow.com/q/14271697/4279). (2) [chiama 'Py_Err_CheckSignals()' invece di manuall che chiama il gestore di segnale Python] (http://stackoverflow.com/a/33652496/4279) – jfs

5

Tuttavia, Ctrl-C non sembra avere alcun effetto

Ctrl-C in the shell sends SIGINT to the foreground process group. python alla ricezione del segnale imposta un flag nel codice C. Se l'estensione C viene eseguita nel thread principale, non verrà eseguito alcun gestore di segnale Python (e quindi non vedrai l'eccezione KeyboardInterrupt su Ctrl-C) a meno che non chiami lo PyErr_CheckSignals() che controlla il flag (significa: non dovrebbe rallentarti) ed esegue i gestori di segnale Python se necessario o se la simulazione consente l'esecuzione del codice Python (ad esempio, se la simulazione utilizza i callback Python). Se l'estensione viene eseguita in un thread in background, è sufficiente rilasciare GIL (per consentire l'esecuzione del codice Python nel thread principale che consente l'esecuzione dei gestori di segnale).

correlati: Cython, Python and KeybordInterrupt ingored

Problemi correlati