return 与 Python 的区别 2 --version check 和 Python 3

Difference between return from Python 2 --version check and Python 3

为什么 运行 中的 return --version 检查 Python 2 的行为与 Python 3 的行为不同?下面是将输出写入文本文件并随后检查该文件内容时的两种行为的示例。

C:\Users\user1>C:\Python27\python.exe --version >> file2.txt
Python 2.7.13

C:\Users\user1>type file2.txt

C:\Users\user1>C:\Python38\python.exe --version >> file3.txt

C:\Users\user1>type file3.txt
Python 3.8.1

C:\Users\user1>

有什么方法可以产生与 Python 3 相同的行为吗?我想使用 --version 检查命令的输出作为批处理文件的一部分,以确保使用正确的版本来执行脚本。

Python 2 行为是将 --version 发送到标准错误。这在 Python 3.4 中已更改为标准输出,但出于对破坏性更改的担忧,未向后移植:

您可以redirect stderr确保相同的行为,例如Python MAJOR.MINOR.PATCH 被写入文件。

Python 2 好像是把版本信息输出到STDERR(句柄2)而不是STDOUT (处理1),所以更改:

C:\Python27\python.exe --version >> file2.txt

至:

C:\Python27\python.exe --version 2> file2.txt

redirection运算符>>用于追加到一个文件;要(过度)写入,请改用 >

要将 STDOUTSTDERR 写入文件,请使用此(将 ?? 替换为 2734):

C:\Python??\python.exe --version > "file.txt" 2>&1

表达式2>&1表示将句柄2重定向到句柄1的当前目标,这是由于> "file.txt"而给定的文本文件。请注意 > 等同于 1>,因为输出重定向的默认句柄是 1 (STDOUT)。这里的顺序很重要(所以 2>&1 > "file.txt" 会失败)。

这在附加到文件时也有效:

C:\Python??\python.exe --version >> "file.txt" 2>&1

要在没有(临时)文件的情况下将结果直接存入变量,请使用 for /F loop – in :

for /F "delims=" %V in ('C:\Python??\python.exe --version 2^>^&1') do set VAR=%V

并在 :

for /F "delims=" %%V in ('C:\Python??\python.exe --version 2^>^&1') do set VAR=%%V

请注意使用 ^escaping,这是避免过早尝试重定向所必需的。

要仅将纯版本号存储到前面没有单词 Python 的变量中,请将 delims= 替换为 tokens=2


让我们更进一步:您可以让 自行搜索所有可用的 Python 版本。鉴于包含 python.exe 的目录路径列在 系统变量 PATH 中,您可以使用 where 获取可执行文件的完整路径,然后让 for /F 循环遍历它们以获取它们的确切版本(版本号只是为了演示而在此处回显):

@echo off
for /F "delims=" %%W in ('where python') do (
    for /F "tokens=2" %%V in ('"%%W" --version 2^>^&1') do (
        echo %%V
    )
)

如果 PATH 变量不包含路径,您也可以使用 for /D (here ?? is meant literally as wildcards) 搜索所有路径 C:\Python??); where 只是检查是否真的有一个文件 python.exe:

@echo off
for /D %%X in ("%SystemDrive%\Python??") do (
    for /F "delims=" %%W in ('where "%%~X":python 2^> nul') do (
        for /F "tokens=2" %%V in ('"%%W" --version 2^>^&1') do (
            echo %%V
        )
    )
)