Python 带cwd参数的subprocess.run()是否只有在Windows上shell=True时才起作用?

Python 带cwd参数的subprocess.run()是否只有在Windows上shell=True时才起作用?,python,windows,subprocess,Python,Windows,Subprocess,在Windows上,具有以下目录结构: C:\Users\me\Documents ├── bin │   └── pv.exe └── dev    └── script.py 和C:Users\me\Documents\dev作为Python解释器(v3.8.5)的工作目录: 对可执行工作的以下调用: >>> subprocess.run(["../bin/pv.exe"]) CompletedProcess(args=['../bin/pv.exe

在Windows上,具有以下目录结构:

C:\Users\me\Documents
├── bin
│   └── pv.exe
└── dev
    └── script.py
C:Users\me\Documents\dev
作为Python解释器(v3.8.5)的工作目录:

对可执行工作的以下调用:

>>> subprocess.run(["../bin/pv.exe"])
CompletedProcess(args=['../bin/pv.exe'], returncode=0)
>>> subprocess.run(["pv.exe"], cwd="../bin", shell=True)
CompletedProcess(args=['pv.exe'], returncode=0)
但以下调用失败:

>>> subprocess.run(["pv.exe"], cwd="../bin")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python38\lib\subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Program Files\Python38\lib\subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Program Files\Python38\lib\subprocess.py", line 1307, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified
>>子流程.run([“pv.exe”],cwd=“../bin”)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“C:\Program Files\Python38\lib\subprocess.py”,第489行,正在运行
使用Popen(*popenargs,**kwargs)作为流程:
文件“C:\Program Files\Python38\lib\subprocess.py”,第854行,在\uuu init中__
self.\u execute\u child(参数、可执行文件、预执行文件、关闭文件、,
文件“C:\Program Files\Python38\lib\subprocess.py”,第1307行,在执行子进程中
hp、ht、pid、tid=\u winapi.CreateProcess(可执行文件、参数、,
FileNotFoundError:[WinError 2]系统找不到指定的文件
当我在路径中使用
\\
而不是
/
,或者使用
/pv.exe而不是
pv.exe
,或者使用从
C:
开始的绝对路径作为
cwd
时,结果是一样的。我想我已经尝试了所有组合

为什么?唯一的声明是:

如果cwd不是
None
,则函数会在执行子级之前将工作目录更改为cwd。cwd可以是字符串、字节或类似路径的对象。特别是,如果可执行路径是相对路径,则函数会查找相对于cwd的可执行文件(或参数中的第一项)

  • 它看起来不像描述的那样

  • 文档中没有提到
    shell
    必须是
    True
    。我不想使用
    shell=True
    ,因为我不会用驳船杆接触
    cmd.exe
    shell和可执行文件名(
    pv.exe
    )它的参数实际上将在比这个MWE更现实的场景中由用户提供(因此存在安全隐患,IIUC)


  • 我是否误解了文档?

    文档有误导性。引用的行仅适用于基于
    fork
    的POSIX实现。Windows实现调用
    CreateProcessW
    ,它解析当前进程上下文中的可执行路径。即使使用
    shell=True
    ,您也应该明确参考在命令行中将工作目录显示为“.”,例如
    r.\pv.exe'
    (在本例中仅使用反斜杠,而不是正斜杠)。问题是,可以从CMD的搜索中排除隐式搜索工作目录(以及
    CreateProcessW
    )通过定义名为的环境变量。另外,对于将代码移植到Windows的POSIX程序员,不要从命令行解析可执行路径,例如解析为
    argv[0]的路径
    。命令行中的相对路径与父级的工作目录相对,这可能完全不同。在Windows中解析可执行路径的方法是通过
    getModuleFileName
    NULL
    作为模块句柄。
    >>> subprocess.run(["pv.exe"], cwd="../bin")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Program Files\Python38\lib\subprocess.py", line 489, in run
        with Popen(*popenargs, **kwargs) as process:
      File "C:\Program Files\Python38\lib\subprocess.py", line 854, in __init__
        self._execute_child(args, executable, preexec_fn, close_fds,
      File "C:\Program Files\Python38\lib\subprocess.py", line 1307, in _execute_child
        hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
    FileNotFoundError: [WinError 2] The system cannot find the file specified