I have the following python code:
var_b='en'
var_c='cs'
var_d='false'
var_e=str(Path.home())
IDS='TEST_123'
L1 = [1, 2 , 3, 4]
L2 = ['env', L1, f'a={var_b}']
CMD = ['COMMAND']
L3 = [IDS]
L4 = [f'--b {var_b}', f'--c {var_c}']
L5 = [f'--d {var_d}', f'--e {var_e}.xml', L4]
I would like to execute a terminal command using subprocess to make the end command entry on the terminal looks in the combination L2 CMD L3 L5
i.e.
**L2 CMD L3 L5**
env 1 2 3 4 a=en COMMAND TEST_123 --d false --e /path/to/home.xml --b en --c cs
Here is what i have tried:
subprocess.run([*L2, *CMD, *L3, *L5])
But i'm getting this error:
TypeError: expected str, bytes or os.PathLike object, not list
Could someone please suggest how to implement this.
CodePudding user response:
For the case if L2 contains some L6 as and so on, there must be recursion:
var_b='en'
var_c='cs'
var_d='false'
var_e=str("Path.home()")
IDS='TEST_123'
L1 = [1, 2 , 3, 4]
L2 = ['env', L1, f'a={var_b}']
CMD = ['COMMAND']
L3 = [IDS]
L4 = [f'--b {var_b}', f'--c {var_c}']
L5 = [f'--d {var_d}', f'--e {var_e}.xml', L4]
def build_string_recursively(command_list):
ret = []
for command in command_list:
if isinstance(command,list):
ret =build_string_recursively(command)
else:
ret.append(command)
return ret
print(build_string_recursively(L2 CMD L3 L5))
This also gives desired:
['env', 1, 2, 3, 4, 'a=en', 'COMMAND', 'TEST_123', '--d false', '--e Path.home().xml', '--b en', '--c cs']
CodePudding user response:
The problem is that this unpacking *
goes only one level deep. But you want to unpack every level in order to get a flat list. You should do something like this:
import itertools
from pathlib import Path
def flatten_to_strings(l):
"""Flatten a list or tuple, turning the remaining components into strings."""
if not isinstance(l, (list, tuple)):
return [str(l)]
flat = (flatten_to_strings(i) for i in l)
return list(itertools.chain.from_iterable(flat))
With this and your code, you can do
print(flatten_to_strings([*L2, *CMD, *L3, *L5]))
and it prints
['env', '1', '2', '3', '4', 'a=en', 'COMMAND', 'TEST_123', '--d false', '--e /home/glglgl.xml', '--b en', '--c cs']
Alternatively, you could assemble your lists as you need them to be:
L1 = [str(i) for i in [1, 2, 3, 4]] # so that they are strings
L2 = ['env', *L1, f'a={var_b}'] # unpack L1 early
CMD = ['COMMAND']
L3 = [IDS]
L4 = [f'--b {var_b}', f'--c {var_c}']
L5 = [f'--d {var_d}', f'--e {var_e}.xml', *L4] # unpack L4 early
This way,
print([*L2, *CMD, *L3, *L5])
gives
['env', '1', '2', '3', '4', 'a=en', 'COMMAND', 'TEST_123', '--d false', '--e /home/glglgl.xml', '--b en', '--c cs']
as well.