[Python-ideas] String interpolation: environment variables, command substitution

Andrew Barnert abarnert at yahoo.com
Wed Aug 26 23:30:50 CEST 2015


On Aug 26, 2015, at 12:16, Mike Miller <python-ideas at mgmiller.net> wrote:
> 
> Hi,
> 
> The use case is for shell-script replacements, which can be but are often not typically cross-platform.   Let's try different examples:
> 
>    >>> x'version: {$(/usr/bin/xdpyinfo -version)}'  # capture
>    'version: xdpyinfo 1.3.1'

People who expect this to work will likely expect to be able to break the results into separates "arguments", with the bash quoting rules. People already ask on StackOverflow why things like this don't work:

    subprocess.call('files=$(ls)', shell=True)
    subprocess.call('cp $files %s' % dest, shell=True)

No matter how many places they try to put the quotes, or braces, or where they add extern, still nothing gets copied.

With your change, they can fix it like this:

    files = x'{$(ls)}'
    subprocess.call(x'cp {files} {dest}')

... and now it seems to work, except that it's actually not copying any files with spaces in the name. They may not even notice, which is bad. But if they do, no matter where you add the quotes or braces, there's no way to fix it. A Python string value is not a bash array value that stringifies itself in different ways depending on the quoting context. The right answer is still to actually use the shell by cramming it into one line, to get the output as a list of lines and insert each line as a quoted argument, or, best of all, to just use listdir and shutil in the first place instead of trying to translate from Bash to Python one word at a time, which  works about as well as one-abstract word one-abstract instance that manner Japanese from English to translating.



More information about the Python-ideas mailing list