Windows子流程.打开一个没有shell的批处理文件=True



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

>>> import subprocess
>>> subprocess.Popen(['lessc'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:Python27libsubprocess.py", line 679, in __init__
    errread, errwrite)
  File "C:Python27libsubprocess.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>

我能做什么使lessc运行不使用shell=True ?

从https://docs.python.org/3/library/subprocess.html#subprocess.Popen和https://docs.python.org/2/library/subprocess.html#subprocess.Popen:

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

已经被@JBernardo引用。

那么,让我们试试:

where lessc实际上告诉

C:UsersmynameAppDataRoamingnpmlessc
C:UsersmynameAppDataRoamingnpmlessc.cmd

这意味着要执行的文件是lessc.cmd,而不是某个.bat文件。事实上:

>>> import subprocess
>>> subprocess.Popen([r'C:UsersmynameAppDataRoamingnpmlessc.cmd'])
<subprocess.Popen object at 0x035BA070>
>>> lessc: no input files
usage: lessc [option option=parameter ...] <source> [destination]

所以,如果你指定了完整路径,这个可以工作。我猜当你有这样的经历时,一定是打错字了。也许你写的是.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.bat,或者创建调用lessc.bat的.bat文件。这样,该文件将被Windows识别为批处理文件,并将被正确执行。

您可能还需要根据.bat文件的位置设置cwd。

最新更新