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.

Asked By: George Vassilakis

||

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())])
Answered By: no_hex
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.