1

I am trying to assign the output of the command python --version to a variable in batch script but it does not work. Here is the sample code I am using

FOR /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
SET message=%%F
)
ECHO %message%

Although it prints the version for python, it does not assign to the variable var. If I use another command instead of python --version then the output is correctly assigned. e.g. using dir works.

What could be wrong?

NOTE -

@echo off 
set message=Hello

FOR /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
SET message=%%F
)
ECHO %message%
PAUSE

OUTPUT -

C:\Users\nik>extra.bat
Python 2.7.9
Hello
Press any key to continue . . .
nik
  • 23
  • 3
  • 1
    In such cases, try to redirect the output to `NUL`, like `python --version > NUL`. If you can still see the version, the program doesn't output to stdout – jeb Oct 03 '21 at 09:41
  • Good idea, but I can't use `> NUL` redirection in the above code. Also, other command's output could be assigned to the variable except for `python --version` – nik Oct 03 '21 at 10:17
  • @nik why not? any way without redirection your code works completely fine on my PC – phuclv Oct 03 '21 at 10:26
  • @jeb tried on my PC, `python --version` does print to stdout – phuclv Oct 03 '21 at 10:27
  • 1
    How can it output the version when the variable isn't defined? `echo %var%` is the only thing in your code that outputs to screen. – Stephan Oct 03 '21 at 10:49
  • @Stephan have updated the question with complete code. – nik Oct 03 '21 at 11:10
  • @phuclv i have updated code for your reference – nik Oct 03 '21 at 11:16
  • Try `python --version > test.txt` If you still see the output in the screen, then `python` doesn't send output to `stdout`; otherwise, you _should_ get in your `message` variable the contents of `test.txt` – Aacini Oct 03 '21 at 11:47
  • @Aacini when i changed as you suggested, i get the error as `> was unexpected at this time.` – nik Oct 03 '21 at 11:49
  • 1
    No. Open a command-line window and then, at the command prompt, just type: `python --version > test.txt` Don't run your .bat file! – Aacini Oct 03 '21 at 11:50

1 Answers1

1

The installed version of Python outputs obviously the version information to handle STDERR (standard error) instead of handle STDOUT (standard output). For that reason it is necessary to redirect the standard error stream with the version information to standard output stream using 2>&1 as described by Microsoft in the documentation about Using command redirection operators.

The command line to use is:

for /F "delims=" %%I in ('python.exe --version 2^>^&1') do set "message=%%I"

The redirection operators > and & must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR.

FOR respectively cmd.exe processing the batch file with this command line starts in background one more command process with %ComSpec% /c and the command line specified within ' appended as additional arguments. Therefore is executed with Windows installed into C:\Windows in the background:

C:\Windows\System32\cmd.exe /c python.exe --version 2>&1

The command process in background searches now for an executable python.exe as described at What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? When the file python.exe could be found by cmd.exe running in background without a visible console window, it executes it and Python outputs the version information to standard error stream which is redirected to standard output stream of the background command process.

The started cmd.exe closes itself after python.exe terminated itself after printing the version information.

The cmd.exe instance processing the batch file captures everything written to handle STDOUT of started background command process and FOR processes the captured lines after started cmd.exe closed itself.

There is split up by default a non-empty captured line into substrings using normal space and horizontal tab as string delimiters. If the first substring after removal of 0 or more leading spaces/tabs starts with a semicolon, the captured line is ignored, otherwise the first substring is assigned to the specified loop variable I.

The default line handling behavior is not wanted here. For that reason the for /F option delims= defines an empty list of string delimiters to disable the line splitting behavior to get the entire captured line assigned to the specified loop variable I. The implicit default eol=; (semicolon is end of line) can be kept in this case as the version information output by Python starts never with a semicolon.

Mofi
  • 46,139
  • 17
  • 80
  • 143