Why won't subprocess.run take a list of arguments?
Question:
I am running a script called mini_medsmaker.py
, and in that script I am using subprocess.run to call another script called mini_mocks.py
.
I am using argparse to list my arguments, and this is the command I am running:
subprocess.run(["python", "/path/to/mini_mocks.py", *vars(args).values()])
Whenever I run it, I get this error:
Traceback (most recent call last):
File "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_medsmaker.py", line 86, in <module>
rc = main(args)
File "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_medsmaker.py", line 81, in main
subprocess.run(["python", "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_mocks.py", *vars(args).values()])
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 488, in run
with Popen(*popenargs, **kwargs) as process:
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 800, in __init__
restore_signals, start_new_session)
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 1482, in _execute_child
restore_signals, start_new_session, preexec_fn)
TypeError: expected str, bytes or os.PathLike object, not list
However, I thought subprocess.run
could take lists as an object? How can I fix this?
I have tried converting it to both a JSON and a string, but then my mini_mocks.py file can’t take it as an argument.
Answers:
subprocess.run
does support a list of arguments, however if the list contains anything more than a string, bytes or os.PathLike
objects it would fail at:
# subprocess.py: line 608 in the list2cmdline function
for arg in map(os.fsdecode, seq):
bs_buf = []
Because the os.fsdecode
method only gets a filename in the form of strings, bytes or os.PathLike
as mentioned above, and returns the decoded filename. Here you are trying to map every value
of the vars(...)
dictionary, and some of the values are lists (and maybe more unwanted types such as functions etc..) which the fsdecode
cannot execute upon.
Make sure that you refine each value in *vars(A).values()
such that only the mentioned types above are in:
subprocess.run(["python", "./your_path.py", *filter(lambda x: type(x) in [str, bytes, os.PathLike], vars(args).values())])
Or if you want the literal string of the list:
subprocess.run(["python", "./your_path.py", *map(str, vars(args).values())])
I am running a script called mini_medsmaker.py
, and in that script I am using subprocess.run to call another script called mini_mocks.py
.
I am using argparse to list my arguments, and this is the command I am running:
subprocess.run(["python", "/path/to/mini_mocks.py", *vars(args).values()])
Whenever I run it, I get this error:
Traceback (most recent call last):
File "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_medsmaker.py", line 86, in <module>
rc = main(args)
File "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_medsmaker.py", line 81, in main
subprocess.run(["python", "/work/mccleary_group/vassilakis.g/superbit-metacal/superbit_lensing/medsmaker/scripts/mini_mocks.py", *vars(args).values()])
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 488, in run
with Popen(*popenargs, **kwargs) as process:
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 800, in __init__
restore_signals, start_new_session)
File "/work/mccleary_group/vassilakis.g/miniconda3/envs/sbclone2/lib/python3.7/subprocess.py", line 1482, in _execute_child
restore_signals, start_new_session, preexec_fn)
TypeError: expected str, bytes or os.PathLike object, not list
However, I thought subprocess.run
could take lists as an object? How can I fix this?
I have tried converting it to both a JSON and a string, but then my mini_mocks.py file can’t take it as an argument.
subprocess.run
does support a list of arguments, however if the list contains anything more than a string, bytes or os.PathLike
objects it would fail at:
# subprocess.py: line 608 in the list2cmdline function
for arg in map(os.fsdecode, seq):
bs_buf = []
Because the os.fsdecode
method only gets a filename in the form of strings, bytes or os.PathLike
as mentioned above, and returns the decoded filename. Here you are trying to map every value
of the vars(...)
dictionary, and some of the values are lists (and maybe more unwanted types such as functions etc..) which the fsdecode
cannot execute upon.
Make sure that you refine each value in *vars(A).values()
such that only the mentioned types above are in:
subprocess.run(["python", "./your_path.py", *filter(lambda x: type(x) in [str, bytes, os.PathLike], vars(args).values())])
Or if you want the literal string of the list:
subprocess.run(["python", "./your_path.py", *map(str, vars(args).values())])