Python subprocess.call有效但subprocess.check_call没有 - 有什么区别?

时间:2012-06-12 02:11:03

标签: python subprocess

我正在使用Python 2.7

我正在尝试从Python运行StatTransfer程序。

当我尝试:

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)

请注意,如果我从Windows命令行运行“st convert.stc”,它运行得很好,并在上面给出了相同的日志消息。它确实实现了convert.stc中的内容。

这表明使用subprocess.check_call调用StatTransfer程序。但是,最后会出现错误。这有什么错误?我该如何避免呢?我应该使用哪两个命令以及为什么?

ETA :在下面的 mgilson 之后,我从subprocess.call返回值并获取-1。这是什么意思?为什么程序仍在运行,我似乎没有注意到任何真正的错误?

关于我应该如何做到的任何可能的解释和建议?

感谢。

1 个答案:

答案 0 :(得分:4)

可能发生的情况是您的流程退出时具有非零退出状态。要进行检查,请使用retcode=subprocess.call(...)运行,然后打印retcode

如果subprocess.check_call(上方)非零,则

retcode会引发异常。

您看到的异常来自您的try / except子句中的raise subprocess.CalledProcessError

>>> 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命令行检查退出状态(How do I get the application exit code from a Windows command line?)来检查以确保行为相同。我猜测退出状态仍然是-1 - 如果不是,你的程序正在与环境(例如环境变量)进行交互,当你使用python调用它时,它们会有所不同。

最终,如果程序执行了您希望它执行的操作,并且您不关心退出状态,那么您应该只使用subprocess.call,但我建议您查看程序退出程序代码并查看-1的退出状态实际意味着什么。