Python subprocess run() with multiple arguments on Windows
Question:
I’ve run into a problem trying to start a game with some additional parameters. Normally you enter them in the "target line" on Windows, such as:
"C:PathTogame.exe" --arg --arg2 --arg3 abc --arg4 xyz
There are both arguments that are simply the argument like –arg and –arg2, then there are other arguments that require another value, such as "–arg3 50".
I have already figured out how to run multiple arguments in a fixed manner such as below, "localconfig_data["exe"]" contains the path as "C:PathTogame.exe".
subprocess.run([localconfig_data["exe"], "--editor", "--erode 100"])
My issue is that depending on previous selections in my program, I could end up with around 10 different arguments which makes it quite impractical to make cases for all different options.
What I’ve tried that doesn’t work:
args_string = "--editor --erode 100 --hidden-hud" #args_string is made in a for loop depending on the arguments given
subprocess.run([localconfig_data["exe"], args_string])
Outcome is that nothing happens. My next best idea was to try to print it out:
args_list = ["--editor", "--erode 100", "--hidden-hud"]
subprocess.run([localconfig_data["exe"], for a in args_list: print(a)])
This gives me a syntax error: SyntaxError: did you forget parentheses around the comprehension target?, so it was a proof of concept in my mind.
Final question: how can I add all of my arguments dynamically when launching a program with subprocess.run() ?
Answers:
Found the solution to this after some testing. What I ended up doing was building a string for the entire command to execute at once. First part of the string was subprocess.run() with the path, followed by a for loop with all the arguments and finally the closing brackets for the subprocess. Example below.
argslist = ["--arg1", "--arg2", "--arg3"]
executeString = 'subprocess.run([localconfig_data["exe"]'
for argument in argslist:
executeString += ', "'
executeString += argument
executeString += '"'
executeString += "])"
print(executeString)
>>> subprocess.run([localconfig_data["exe"], "--arg1", "--arg2", "--arg3"])
If one argument contains more than one word, such as "–argument value", you just pass this as 2 following values, as "–argument", "value".
The subprocess.run function expects the whole command as list of arguments. So assuming you’d want to execute the command
$ "C:PathTogame.exe" --arg --arg2 --arg3 abc --arg4 xyz
you need to call subprocess.run
with the list ['C:PathTogame.exe', '--arg', '--arg2', '--arg3', 'abc', '--arg4', 'xyz']
:
subprocess.run(['C:PathTogame.exe', '--arg', '--arg2', '--arg3', 'abc', '--arg4', 'xyz'])
The problem with the way you do it, is that you put a list inside of an other list, you need all the arguments on the same level. You can acieve this by unpacking the arguments list into the calling list.
>>> ['app.exe', args_list]
['app.exe', ['--editor', '--erode 100', '--hidden-hud']]
>>> ['app.exe', *args_list] # unpacking
['app.exe', '--editor', '--erode 100', '--hidden-hud']
So:
subprocess.run([localconfig_data["exe"], *args_string])
Your attempt with the list was right, list comprehension doesn’t work with fixed list elements because of scopal ambiguity ([a, b for b in some_list]
could mean [(a, b) for b in some_list]
as well as [a, (b) for b in some_list]
, hence the insistence on parantheses).
I’ve run into a problem trying to start a game with some additional parameters. Normally you enter them in the "target line" on Windows, such as:
"C:PathTogame.exe" --arg --arg2 --arg3 abc --arg4 xyz
There are both arguments that are simply the argument like –arg and –arg2, then there are other arguments that require another value, such as "–arg3 50".
I have already figured out how to run multiple arguments in a fixed manner such as below, "localconfig_data["exe"]" contains the path as "C:PathTogame.exe".
subprocess.run([localconfig_data["exe"], "--editor", "--erode 100"])
My issue is that depending on previous selections in my program, I could end up with around 10 different arguments which makes it quite impractical to make cases for all different options.
What I’ve tried that doesn’t work:
args_string = "--editor --erode 100 --hidden-hud" #args_string is made in a for loop depending on the arguments given
subprocess.run([localconfig_data["exe"], args_string])
Outcome is that nothing happens. My next best idea was to try to print it out:
args_list = ["--editor", "--erode 100", "--hidden-hud"]
subprocess.run([localconfig_data["exe"], for a in args_list: print(a)])
This gives me a syntax error: SyntaxError: did you forget parentheses around the comprehension target?, so it was a proof of concept in my mind.
Final question: how can I add all of my arguments dynamically when launching a program with subprocess.run() ?
Found the solution to this after some testing. What I ended up doing was building a string for the entire command to execute at once. First part of the string was subprocess.run() with the path, followed by a for loop with all the arguments and finally the closing brackets for the subprocess. Example below.
argslist = ["--arg1", "--arg2", "--arg3"]
executeString = 'subprocess.run([localconfig_data["exe"]'
for argument in argslist:
executeString += ', "'
executeString += argument
executeString += '"'
executeString += "])"
print(executeString)
>>> subprocess.run([localconfig_data["exe"], "--arg1", "--arg2", "--arg3"])
If one argument contains more than one word, such as "–argument value", you just pass this as 2 following values, as "–argument", "value".
The subprocess.run function expects the whole command as list of arguments. So assuming you’d want to execute the command
$ "C:PathTogame.exe" --arg --arg2 --arg3 abc --arg4 xyz
you need to call subprocess.run
with the list ['C:PathTogame.exe', '--arg', '--arg2', '--arg3', 'abc', '--arg4', 'xyz']
:
subprocess.run(['C:PathTogame.exe', '--arg', '--arg2', '--arg3', 'abc', '--arg4', 'xyz'])
The problem with the way you do it, is that you put a list inside of an other list, you need all the arguments on the same level. You can acieve this by unpacking the arguments list into the calling list.
>>> ['app.exe', args_list]
['app.exe', ['--editor', '--erode 100', '--hidden-hud']]
>>> ['app.exe', *args_list] # unpacking
['app.exe', '--editor', '--erode 100', '--hidden-hud']
So:
subprocess.run([localconfig_data["exe"], *args_string])
Your attempt with the list was right, list comprehension doesn’t work with fixed list elements because of scopal ambiguity ([a, b for b in some_list]
could mean [(a, b) for b in some_list]
as well as [a, (b) for b in some_list]
, hence the insistence on parantheses).