【问题标题】:subprocess.call() works differently from script and interpretersubprocess.call() 与脚本和解释器的工作方式不同
【发布时间】:2014-02-21 06:16:04
【问题描述】:

希望通过以下代码从 python 脚本运行二进制文件:

def runner(output_file):
  result = 1

  try:
      image_name = re.sub(r'\..*', '.png', output_file)
      args = ['dot', output_file, '-Tpng', '-o', image_name]
      result = subprocess.call(args)

      if(result == 0):
          print('Graph is rendered to {0}'.format(image_name))

  except:
      print('ERROR: Cannot run DOT. Please check your PATH')

  return result

当我调用这个函数时,它返回0,一切似乎都正常,但是没有生成文件

当我从 Python 解释器做同样的事情时:

Python 2.7.5+ (default, Sep 19 2013, 13:48:49) 
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> output_file = 'out.dot'
>>> image_name = 'out.png'
>>> args = ['dot', output_file, '-Tpng', '-o', image_name]
>>> subprocess.call(args)

文件生成成功

我尝试设置错误的名称,但在脚本中出现错误(如预期的那样)。从脚本调用pwd 给了我一个正确的目录。使用硬编码值调用与使用变量调用相同。

我做错了什么?

【问题讨论】:

  • 也许你应该使用 shell=True 运行?
  • 在调用subprocess.call之前尝试print args
  • 您是如何(以及在​​哪个目录下)运行脚本的?
  • 此外,虽然这里似乎没有出现问题,但没有充分的理由使用裸 except: 子句。我建议不要使用它,除非你有充分的理由这样做,因为它可以隐藏你不期望的异常。
  • @JayanthKoushik 不。不要不要使用shell=True,尤其是在参数列表中。当shell=True 列表的第一个元素作为整个命令行时,所有其他元素作为选项传递给shell。这显然 不是 OP 想要的。

标签: python python-2.7 subprocess


【解决方案1】:

这里有一些提示可能有帮助。

首先:根据我的经验,args = [...] 容易出错。

shlex.split('dot {0} -Tpng -o {1}'.format(input_file, image_name))

通常更健壮。但是,它要求您正确转义文件名中的空格...

第二:你的 args 中的输入和输出文件是否颠倒了?还是只是变量命名不当?

第三:请不要使用diaper antipattern,例如 python 的禅宗和你自己的理智。 except:

第四:依赖$PATH 和/或使用二进制的非绝对路径肯定会在某些时候中断 - 使用完整的/path/to/dot 作为您的第一个参数。

【讨论】:

  • 我完全不同意 shlex 方法的稳健性。你必须小心,但如果你这样做,事情会更好 - 正如你所说,尤其是文件名及其转义。
  • shlex.split() 没有帮助。你觉得应该怎么用?
猜你喜欢
  • 1970-01-01
  • 2018-02-10
  • 2017-09-24
  • 1970-01-01
  • 2022-08-18
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多