Я использую Python 2.7

Я пытаюсь запустить программу StatTransfer из Python.

Когда я пытаюсь:

tempname = os.path.abspath('./text.txt')
TEMPFILE = open(tempname, 'wb')
try:
    subprocess.check_call('ST convert.stc', shell = True, stdout = TEMPFILE, stderr = TEMPFILE)
except:
    raise CritError(messages.crit_error_bad_command)

Это не удается (CritError определяется пользователем).

Трассировка мне ничего полезного не говорит:

Traceback (most recent call last):
  File "C:\...\py\run_program.py", line 181, in run_stcmd
    run.execute_run(current_directory, posix_command, nt_command)
  File "C:\...\py\private\runprogramdirective.py", line 99, in execute_run
    raise CritError(messages.crit_error_bad_command)
CritError: 'ERROR! Cannot execute command'

Однако изменение соответствующей строки на:

subprocess.call('ST convert.stc', shell = True, stdout = TEMPFILE, stderr = TEMPFILE)

Он работает успешно.

Самое смешное, что я вижу одно и то же в моем TEMPFILE для обоих случаев:

|/-|/-|/-|/-|/- |/-|/-|/-|/-|/- Stat/Transfer - Command Processor (c) 1986-2011 Circle         Systems, Inc.
www.stattransfer.com 
Version 10.1.1866.0714 (32 Bit) - 64 Bit Windows

Serial: ADR4H-L3A3A-N8RJ
User:   XXXXXXXXXXX
Your license is in its grace period -- Please call Circle Systems
Your program will die at the end of the month
Status: Temporarily OK (Expired May 31, 2012)
Transferring from SPSS Portable File: ..\orig\10908970\ICPSR_03775\DS0001\03775-0001-    Data.por
Input file has 26 variables
Optimizing...
Transferring to Stata: ..\data\ABCFeb.dta

504 cases were transferred(0.02 seconds)

Обратите внимание, что если я запускаю "st convert.stc" из командной строки Windows, он работает нормально и выдает то же сообщение журнала, что и выше. Он действительно выполняет то, что написано внутри convert.stc.

Это говорит о том, что программа StatTransfer вызывается с subprocess.check_call. Однако в конце есть ошибка. Что это за ошибка? Как мне этого избежать? Какую из 2 команд мне следует использовать и почему?

ETA . Следуя приведенному ниже mgilson , я возвращаю значение из subprocess.call и получаю -1. Что это значит? Почему программа все еще работала, и я не заметил никаких реальных ошибок?

Любые возможные объяснения и предложения о том, как мне это сделать здесь?

Спасибо.

5
cinny 12 Июн 2012 в 06:11
4
Вы должны опубликовать всю трассировку - например, какая строка вызывает ошибку. Ваше предложение try / except также, вероятно, маскирует проблему, потому что вы ловите любую ошибку, а затем вызываете что-то другое (без аргументов)
 – 
mgilson
12 Июн 2012 в 06:15
Извините за исключение. Изначально у меня был пользовательский. Это не говорит мне ничего полезного, кроме того, что вызов подпроцесса завершился неудачно - вот и все. Вопрос обновлен.
 – 
cinny
12 Июн 2012 в 06:36

1 ответ

Лучший ответ

Вероятно, происходит то, что ваш процесс завершается с ненулевым статусом выхода. Чтобы проверить, запустите с retcode=subprocess.call(...), а затем напечатайте retcode.

subprocess.check_call вызовет исключение, если retcode (выше) не равно нулю.

Вы видите исключение из raise subprocess.CalledProcessError в предложении try / except:

>>> import subprocess 
>>> raise subprocess.CalledProcessError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 3 arguments (1 given)

ИЗМЕНИТЬ

Я бы все равно переписал предложение try / except, поскольку вы перехватываете исключение и генерируете другое (что означает, что вся информация в исходном сообщении теряется).

Попробуйте что-нибудь вроде:

try:
    subprocess.check_call('ST convert.stc', shell = True, stdout = TEMPFILE, stderr = TEMPFILE)
except Exception as e:
    raise CritError(messages.crit_error_bad_command+' '+str(e))

Это все равно предоставит вам некоторую ( не всю ) информацию из исходного сообщения. Проблема, вероятно, все еще в том, что ваша подпрограмма завершается с ненулевым кодом выхода. Может быть, это нормально (убедитесь, что он выполнил то, что вы хотите).

Вы сказали, что можете запустить команду из командной строки, и все выглядит нормально. Вы можете убедиться, что поведение такое же, проверив статус выхода из командной строки Windows (Как получить код выхода приложения из командной строки Windows?). Я предполагаю, что статус выхода по-прежнему будет -1. Если это не так, ваша программа взаимодействует с окружающей средой (например, с переменными среды), которые каким-то образом отличаются, когда вы вызываете ее с помощью python.

В конечном итоге, если программа делает то, что вы хотите, и вам не важен статус выхода, тогда вам следует просто использовать subprocess.call, но я бы посоветовал обратиться к руководству по кодам выхода программ и посмотреть что на самом деле означает статус выхода -1.

6
Community 23 Май 2017 в 15:32
Означает ли это, что ошибка есть или нет? Не думаю, что здесь должна быть ошибка. Как мне этого избежать?
 – 
cinny
12 Июн 2012 в 06:29
На самом деле я использовал исключение ошибки конкретного пользователя, а не subprocess.CalledProcessError в моем коде. Я просто быстро изменил его, когда задавал вопрос здесь, поскольку мое собственное исключение не дало мне ничего полезного.
 – 
cinny
12 Июн 2012 в 06:30
: Обычно, когда вы используете пользовательскую ошибку, она возникает как raise UserError("Some message"). Насколько действительно существует ошибка, зависит от программы. Ваша программа возвращает -1. Обычно программа возвращает 0 в случае успеха, что означает, что у вызываемой программы, вероятно, возникла какая-то проблема (или, по крайней мере, она так думает). Значение -1 полностью зависит от программы, поэтому я не могу вам помочь. Полагаю, обратитесь к руководству по этой программе.
 – 
mgilson
12 Июн 2012 в 16:16
Это действительно полезно. В этом конкретном случае программа завершила то, что должна была, поэтому я не видел причин для возврата -1. Дело в том, что моя функция написана так, что команда меняется, поэтому я могу использовать Python и для других вещей. Должен ли я по-прежнему придерживаться subprocess.call, или, может быть, только со StatTransfer я должен разрешить retcode быть <> 0, но не для других?
 – 
cinny
12 Июн 2012 в 19:43
Я попытался проверить руководство StatTransfer в Интернете, но в нем ничего не упоминается о коде выхода. То есть, обычно я не вижу таких подробностей в руководствах. Это довольно неприятно.
 – 
cinny
12 Июн 2012 в 19:44