Home > Net >  Python Subprocess or BAT script splits argument on equal sign
Python Subprocess or BAT script splits argument on equal sign

Time:12-06

How do I add this: -param:abc=def as a SINGLE command line argument?

Module subprocess splits this up in TWO arguments by replacing the equal sign with a space.

Here is my python script:

import subprocess

pa=['test.bat', '--param:abc=def']
subprocess.run(pa)

Here is the test program:

@echo off
echo Test.bat
echo Arg0: %0
echo Arg1: %1
echo Arg2: %2
pause

and here the output:

Test.bat
Arg0: test.bat
Arg1: --param:abc
Arg2: def
Press any key to continue . . .

Because the equal sign is gone, the real app will not be started correctly. By the way, this problem also seems to happen when running on linux, with a sh script instead of a bat file.

I understand that removing the equal sign is a 'feature' in certain cases, e.g. with the argparse module, but in my case I need to keep the equal sign. Any help is appreciated!

CodePudding user response:

Welcome to .bat file hell

To preserve equal sign, you'll have to quote your argument (explained here Preserving "=" (equal) characters in batch file parameters) ('"--param:abc=def"'), but then subprocess will escape the quotes

Test.bat
Arg0: test.bat
Arg1: \"--param:abc=def\"
Arg2:

Good old os.system won't do that

import os

os.system('test.bat "--param:abc=def"')

result

Test.bat
Arg0: test.bat
Arg1: "--param:abc=def"
Arg2:

Damn, those quotes won't go off. Let's tweak the .bat script a little to remove them manually

@echo off
echo Test.bat
echo Arg0: %0
rem those 2 lines remove the quotes
set ARG1=%1
set ARG1=%ARG1:"=%

echo Arg1: %ARG1%
echo Arg2: %2

now it yields the proper result

Test.bat
Arg0: test.bat
Arg1: --param:abc=def
Arg2:

Alternatively, stick to subprocess and remove quotes AND backslashes.

CodePudding user response:

I just checked, and you can use the shlex package to parse the string before sending it to the shell:

import subprocess, shlex

pa = shlex.split('test.bat --param:abc=def')  # parse string into a list

subprocess.run(pa)

Some info on the shlex module: It allows us to split strings using shell-like syntax, which is useful when working with the shell/command line. (docs)

Hope this helps.

CodePudding user response:

As Jean-Francois said, this is caused by BAT file Hell:

C:\>test.bat -param:abc=def
Test.bat
Arg0: test.bat
Arg1: -param:abc
Arg2: def
Press any key to continue . . .

Powershell does a better job, test.ps1:

write-host "There are a total of $($args.count) arguments"
for ( $i = 0; $i -lt $args.count; $i   ) {
    write-host "Argument  $i is $($args[$i])"
} 

Running from the DOS prompt:

PS C:\> .\test.ps1 --params:abc=def
There are a total of 1 arguments
Argument  0 is --params:abc=def

Conclusion:

There is nothing wrong with Python.

Because the app that I need to start from Python has a BAT startup script, I have to replace that by a Powershell version *.ps1 script.

  • Related