在 python 中,如何将数组参数传递给 powershell 脚本

Jim*_*Jim 3 python powershell

我有一个PowerShell脚本,它有两个参数,第一个是字符串,第二个是字符串数组。

我想从我的 python 代码中调用这个 PowerShell 脚本。如何将数组类型参数传递给PowerShell?

如果我写这样的东西:

subprocess.run(['powershell.exe', 'script.ps1', 'arg1', '@("str1", "str2")'])
Run Code Online (Sandbox Code Playgroud)

Powershell 认为 '@("str1", "str2")' 是一个字符串,而不是一个数组。

编辑 我找到了解决方法

subprocess.run(['powershell.exe', 'script.ps1 arg1 @("str1", "str2")'])
Run Code Online (Sandbox Code Playgroud)

它看起来不漂亮,但是有效。这样,我就无法使用-File之后powershell.exe

mkl*_*nt0 5

您的原始命令确实按编写的方式工作除非您必须使用.\script.ps1而不是script.ps1,除非脚本位于系统路径中),您稍后添加的第二个命令也是如此,因为它隐式使用 PowerShell CLI 的-Command参数而不是其
-File参数。

简而言之:

  • 基本上仅支持传递数组-Command,它将后续参数解释为 PowerShell 代码,其中应用通常的 PowerShell 语法。

  • 相比之下-File,目标脚本参数之后的所有参数都作为字符串逐字传递,因此不存在数组的概念

我建议使用以下方法,以提高稳健性和概念清晰度:

subprocess.run(['powershell.exe', '-noprofile', '-c', '.\script.ps1 arg1 @("str1", "str2")'])
Run Code Online (Sandbox Code Playgroud)

注意:您可以省略@(...)数组元素 - @()PowerShell 中的数组文字永远不需要。

笔记:

  • -noprofile确保 PowerShell 不会加载$PROFILE文件,从而避免潜在的速度减慢和副作用。

  • -c( -Command) 明确表明您正在传递PowerShell 代码,而不是带有文字参数的脚本文件( )-File

    • 请注意,-Command参数会受到 PowerShell 的额外解释,因此,如果您传递一个$foo$想要作为文字的标记,PowerShell 会将其扩展为 just $(如果未定义$foo变量),因为它会扩展$foo为变量引用;传递`$foo`$(反引号转义)可以防止这种情况。
  • 请注意.\前面的内容script.ps1:由于您正在使用,因此您不能仅通过文件名-Command执行脚本(除非该脚本恰好位于 中列出的目录中);在 PowerShell 内部,出于安全原因,需要从当前目录执行脚本;相比之下,仅文件名调用确实适用于.$env:PATH.\-File

  • 脚本文件及其参数作为单个参数传递,这反映了 PowerShell 将如何处理命令。

  • -Command是Windows PowerShell中的默认值,但在 PowerShell Core ( )中不再是pwsh.exe默认值,默认为-File; 通常最好显式使用-Command( -c) 或-File( -f) 来明确 PowerShell 将如何解释参数。


如何subprocess.run()构建命令行以及 PowerShell 如何解析它:


您的原始 Python 命令@("str1", "str2")作为单独的参数传递给subprocess.run()

subprocess.run(['powershell.exe', '.\script.ps1', 'arg1', '@("str1", "str2")'])

这会导致在幕后执行以下命令行:

powershell.exe .\script.ps1 arg1 "@(\"str1\", \"str2\")"
Run Code Online (Sandbox Code Playgroud)

请注意如何@("str1", "str2")使用双引号以及如何嵌入 "字符。被转义为\".

顺便说一句:PowerShell 的CLI(传递给 的参数powershell.exe)使用常规的\文字"字符转义。然而,`PowerShell 中, (反引号)充当转义字符。


第二个命令将script.ps1and组合@("str1", "str2")成一个参数

subprocess.run(['powershell.exe', '.\script.ps1 arg1 @("str1", "str2")'])

这会产生以下命令行:

powershell.exe ".\script.ps1 arg1 @(\"str1\", \"str2\")"
Run Code Online (Sandbox Code Playgroud)

请注意传递的单个参数是如何作为一个整体用双引号引起来的。

通常,如果给定参数包含空格,则subprocess.run() 自动将其括在(双引号)中。"..."

独立地,它转义嵌入的(文字)"字符。作为\"


尽管这些命令行明显不同,但 PowerShell 的(隐含)-Command逻辑对它们的处理是相同的,因为它使用以下算法:

  • 首先,删除每个参数周围的双引号(如果存在)。

  • 如果有多个字符串,则结果字符串用空格连接。

  • 然后,生成的单个字符串将作为 PowerShell 代码执行。

如果将此算法应用于上述任一命令行 PowerShell 最终会执行相同的代码,即:

.\script.ps1 arg1 @("str1", "str2")
Run Code Online (Sandbox Code Playgroud)