【问题标题】:Windows subprocess.Popen a batch file without shell=TrueWindows subprocess.Popen 没有 shell=True 的批处理文件
【发布时间】:2013-04-14 18:59:03
【问题描述】:

我有一个运行lessc的函数(与npm install -g less一起安装):

>>> import subprocess
>>> subprocess.Popen(['lessc'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\subprocess.py", line 679, in __init__
    errread, errwrite)
  File "C:\Python27\lib\subprocess.py", line 896, in _execute_child
    startupinfo)
WindowsError: [Error 2] The system cannot find the file specified

不幸的是,除非我添加shell=True,否则它不起作用:

>>> subprocess.Popen(['lessc'], shell=True)
<subprocess.Popen object at 0x01F619D0>

如何在不使用shell=True 的情况下使lessc 运行?

【问题讨论】:

  • 您能否在不使用shell=True 的情况下使用其完整路径名显式调用二进制文件?
  • @kragniz: lessc 是一个批处理文件(这实际上可能是问题所在),当我使用完整路径运行它时会出现同样的错误。
  • 错误是子流程模块本身产生的还是批处理脚本产生的?您可以在 Popen 调用中添加 cwd=r'c:\path\to\script\' 参数
  • @JBernardo:subprocess 模块。因此,如果不编辑脚本本身(它是 Web 框架的资产捆绑器的一部分),就无法解决这个问题?
  • The docs:在带有shell=True 的 Windows 上,COMSPEC 环境变量指定默认 shell。唯一需要在 Windows 上指定 shell=True 的情况是当您希望执行的命令内置到 shell 中时(例如 dir 或 copy)。您不需要shell=True 来运行批处理文件或基于控制台的可执行文件。

标签: python windows shell subprocess


【解决方案1】:

来自https://docs.python.org/3/library/subprocess.html#subprocess.Popenhttps://docs.python.org/2/library/subprocess.html#subprocess.Popen

您不需要shell=True 来运行批处理文件或基于控制台的可执行文件。

已经cited by @JBernardo

那么,让我们试试吧:

where lessc其实告诉了

C:\Users\myname\AppData\Roaming\npm\lessc
C:\Users\myname\AppData\Roaming\npm\lessc.cmd

也就是说,要执行的文件是lessc.cmd,而不是某个.bat 文件。确实:

>>> import subprocess
>>> subprocess.Popen([r'C:\Users\myname\AppData\Roaming\npm\lessc.cmd'])
<subprocess.Popen object at 0x035BA070>
>>> lessc: no input files

usage: lessc [option option=parameter ...] <source> [destination]

所以,如果您指定完整路径,这确实 工作。我认为当您使用this experience 时涉及错字。可能你写的是.bat而不是.cmd


如果您不想将lessc 的完整路径修补到您的脚本中,您可以自己烘焙一个where

import plaform
import os

def where(file_name):
    # inspired by http://nedbatchelder.com/code/utilities/wh.py
    # see also: http://stackoverflow.com/questions/11210104/
    path_sep = ":" if platform.system() == "Linux" else ";"
    path_ext = [''] if platform.system() == "Linux" or '.' in file_name else os.environ["PATHEXT"].split(path_sep)
    for d in os.environ["PATH"].split(path_sep):
        for e in path_ext:
            file_path = os.path.join(d, file_name + e)
            if os.path.exists(file_path):
                return file_path
    raise Exception(file_name + " not found")

然后你可以写:

import subprocess
subprocess.Popen([where('lessc')])

【讨论】:

  • 五年前我问这个问题时,lessc 应该是 1.3.3 版和 npm 1.2.18 版。我目前没有 Windows 环境来测试它,所以从那时起可能发生了一些变化?
【解决方案2】:

将文件更改为lessc.bat,或创建调用lessc 的.bat 文件。这样该文件将被 Windows 识别为批处理文件并正确执行。

除此之外,您可能还需要设置 cwd,具体取决于 .bat 文件的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2012-12-13
    • 2023-04-09
    • 1970-01-01
    • 2014-11-15
    相关资源
    最近更新 更多