A question about a list and subprocess.check_call()

Peter Otten __peter__ at web.de
Mon Feb 16 13:39:52 EST 2015


David Aldrich wrote:

> Hi Peter
> 
> Thanks very much for your reply. I have added one more question below.
> 
>> The straightforward approach is to pass a list or tuple:
>> 
>> def build(build_options=()):
>>     subprocess_check_call(("make",) + build_options)
>> 
>> build(("flagA=true", "flagB=true"))
> 
> This looks fine - I am trying it.
> 
> I would like to display on the console the entire make command, so I have
> done this:
> 
> def build(build_options=()):
>         make_command = 'make '.join(map(build_options))
>         print('Build command: ' + make_command)
>         subprocess.check_call(("make",)+build_options)
> 
> but I get error:
> 
> make_command = 'make '.join(map(build_options))
> TypeError: map() must have at least two arguments.
> 
> What would be the correct way to concatenate and display the elements in
> the tuple please?

Hm, what do you expect map() to achieve? And "make " is not really the 
string you want as a separator...

You can join the strings in build_options with

>>> build_options = "foo", "bar", "baz"
>>> " ".join(build_options)
'foo bar baz'
>>> "make " + " ".join(build_options)
'make foo bar baz'

But you shouldn't do this as you have already learnt that spaces do not 
separate arguments; in fact by default check_call() doesn't even use the 
shell. An example to drive the point home:

>>> from subprocess import check_call
>>> check_call(["python3", "-c", "import sys; print(sys.argv[1:])", "foo", 
"bar"])
['foo', 'bar']
0
>>> check_call(["python3", "-c", "import sys; print(sys.argv[1:])", "foo 
bar"])
['foo bar']

Both invocations would appear to issue the same command in your debugging 
print() call. list2cmdline() does a bit better; it resembles the command 
issued if the shell were used:

>>> print(subprocess.list2cmdline(["make"] + build_options))
make foo "bar baz"





More information about the Python-list mailing list