2011-10-31 14 views
8

Ho scritto uno script bash che sta facendo esattamente quello che voglio fare, ma calciando fuori il seguente errore:Errore di indirizzamento sys.excepthook in script bash

close failed in file object destructor: sys.excepthook is missing lost sys.stderr

Sono completamente perplesso su come affrontare questo. Ecco la sceneggiatura:

#!/bin/bash 

usage() { echo "${0##*/} inputfile outputfile"; exit 1; } 

(($#==2)) || usage 

INPUTFILE="$1" 
OUTPUTFILE="$2" 

# All that is written between between the 'cat' command and 
#+ 'EOF' will be sent to the output file. 
cat <<EOF >$OUTPUTFILE 
$(date "+Generated on %m/%d/%y at %H:%M:%S") 

DATA AUDIT: $1 

------------ 
COLUMN NAMES 
------------ 

$(csvcut -n $INPUTFILE) 

--------------------------------------- 
FIRST TEN ROWS OF FIRST FIVE COLUMNS 
--------------------------------------- 

$(csvcut -c 1,2,3,4,5 $INPUTFILE | head -n 10) 

------------ 
COLUMN STATS 
------------ 

$(csvcut $INPUTFILE | csvstat) 

---END AUDIT 
EOF 

echo "Audited!" 

Sono abbastanza nuovo per gli script di shell e molto nuovo per Python. Sarei grato per qualsiasi aiuto.

+1

L'errore deriva dallo script python (csvcut?), Non dallo script di bash. Sarebbe più utile vedere invece il codice relativo al codice: D –

+0

Potrebbe darsi che a csvcut non piaccia la testa, poiché costringe lo stdout del processo a chiudere prematuramente? –

+0

@ Antti, immagino che sia il caso, ma mi chiedo se ci fosse qualcosa che potrei fare nello script per risolvere il problema, dal momento che l'esecuzione dei comandi individualmente sulla riga di comando non genera l'errore. Hai un'idea di come la testa potrebbe essere cambiata per affrontare un possibile problema di stdout? O il codice csvcut sarebbe ancora necessario per questo? E grazie! –

risposta

18

Stavo vedendo questo errore durante il piping dell'output da uno script Python 2.6.2 nel comando head in bash su Ubuntu 9.04. Ho aggiunto try blocchi per chiudere stdout e stderr prima di uscire lo script:

try: 
    sys.stdout.close() 
except: 
    pass 
try: 
    sys.stderr.close() 
except: 
    pass 

non ho più sto vedendo l'errore.

+0

Qualche spiegazione sul perché questo funziona? Ho ricevuto questo errore in uno script cython che esegue qualche reindirizzamento con dup/dup2 e questo sembra risolvere i problemi. – Snorfalorpagus

+1

Rilevante bug Python: http://bugs.python.org/issue11380 –

+1

La soluzione funziona anche con chiamate a '.flush' invece di' .close'. Non so se questo significhi qualcosa però. ('close' implica 'flush'). Python 2.7.8 su Ubuntu 14.04 –

1

Suppongo che lo script Python csvcut sia in altro modo funzionale ma genera un errore quando tenta di chiudere i file ed uscire.

Se, come dici tu, lo script funziona diversamente e si presuppone che l'errore "csvcut" stia generando output su stderr, reindirizzare a/dev/null sarebbe una correzione temporanea.

cat <<EOF >$OUTPUTFILE 2>/dev/null 

Naturalmente anche altri messaggi di errore nel tuo heredoc reindirizzeranno lì.

+0

Anche come correzione temporanea, non funziona per me. Ottengo sempre lo stesso errore. –

3

ci sono due passaggi da eseguire:

Fase 1:

Nella tua csvcut sceneggiatura, trovare tutti i luoghi dove sys.stdout.write() sono chiamati, assicurarsi sys.stdout.flush() si chiama dopo ogni write().

Fase 2:

Con la fase 1 completato si dovrebbe ora essere in grado di catturare IOError all'interno dello script Python. Di seguito è riportato un esempio su come gestire il tubo rotto:

try: 
    function_with_sys_stdout_write_call() 
except IOError as e: 
    # one example is broken pipe 
    if e.strerror.lower() == 'broken pipe': 
     exit(0) 
    raise  # other real IOError 

Spero che aiuti!

+0

Questa era una correzione corretta nel mio caso. Sembra che un traceback sia stato ancora scritto su stderr mentre lo script stava uscendo e flussare lo stderr prima di uscire ha funzionato. – hayavuk