Устранение ошибки sys.excepthook в скрипте bash

#python #bash #shell #unix

#python #bash #оболочка #unix

Вопрос:

Я написал скрипт bash, который делает именно то, что я хочу, но выдает следующую ошибку:

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

Я совершенно не понимаю, как это решить. Вот сценарий:

 #!/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!"
  

Я довольно новичок в сценариях оболочки и очень новичок в python. Я был бы благодарен за любую помощь.

Комментарии:

1. Ошибка возникает из скрипта python (csvcut?), А не из вашего скрипта bash. Было бы более полезно вместо этого просмотреть соответствующий код: D

2. Может быть, csvcut не нравится заголовок, поскольку он заставляет стандартный вывод процесса преждевременно закрываться?

3. @Antti, я предполагал, что это так, но мне интересно, могу ли я что-то сделать в скрипте, чтобы решить проблему, поскольку выполнение команд по отдельности в командной строке не приводит к возникновению ошибки. Есть ли у вас представление о том, как можно изменить заголовок для решения возможной проблемы стандартного вывода? Или для этого все еще будет необходим код csvcut? И спасибо!

4. почему вы работаете с заменами команд, т. Е. $(csvcut $INPUTFILE | csvstat ) Когда Все, что вам нужно csvcut $INPUTFILE | csvstat . Удачи.

5. Потому что это heredoc, нет? То, что вы предлагаете, не работает. Я неправильно понимаю? Надеюсь, вы продолжите, и спасибо, что вмешались.

Ответ №1:

Я видел эту ошибку при передаче выходных данных из скрипта Python 2.6.2 в head команду в bash Ubuntu 9.04. Я добавил try блоки для закрытия stdout и stderr перед выходом из скрипта:

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

Я больше не вижу ошибки.

Комментарии:

1. Любое объяснение того, почему это работает? Я получаю эту ошибку в скрипте cython, который выполняет некоторое перенаправление с помощью dup / dup2, и это, кажется, все исправляет.

2. Решение также работает с вызовами .flush вместо .close . Я не знаю, означает ли это что-нибудь. ( close подразумевает flush ). Python 2.7.8 на Ubuntu 14.04

3. -u Опция python (небуферизованный вывод) также кажется актуальной. Когда -u передается, я не могу воспроизвести проблему

Ответ №2:

Вам нужно выполнить два шага:

Шаг 1:

В вашем скрипте csvcut найдите все места, где sys.stdout.write() вызываются, убедитесь sys.stdout.flush() , что вызывается после каждого write() .

Шаг 2:

После завершения шага 1 вы теперь сможете выполнять захват IOError в скрипте Python. Ниже приведен один пример того, как обрабатывать поврежденный канал:

 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
  

Надеюсь, это поможет!

Комментарии:

1. В моем случае это было правильное исправление. Похоже, что трассировка все еще записывалась в stderr во время завершения работы скрипта, и сброс stderr перед завершением работы сделал свое дело.

Ответ №3:

Я предполагаю, что скрипт csvcut Python в остальном функционален, но выдает ошибку при попытке закрыть файлы и выйти.

Если, как вы говорите, скрипт работает в противном случае и предполагает, что ошибка ‘csvcut’ выдает выходные данные в stderr, то перенаправление ее в /dev/null будет временным исправлением.

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

Естественно, любые другие сообщения об ошибках в вашем heredoc также будут перенаправляться туда.

Комментарии:

1. Даже в качестве временного исправления это не работает для меня. Все еще получаю ту же ошибку.