AlanK
AlanK

Reputation: 9833

String format python

I'm trying to clean up a bad solution. I have a utils file, which contains some generic methods and a commands file, where I store a list of commands to use within the program. However, when trying to clean up files by using string format, I'm starting to run into problems.

# utils.py
import os

bin = '/usr/bin'
tool = '{0}/tool'.format(bin)
command = '{0} -dir %s -o geniso'.format(tool)

def exec_cmd(cmd):
    os.system(cmd)

# dowork.py
from utils import *
exec_cmd(command % '/var/tmp')

In the example you can see, I'm trying to clean up the commands/utils by concatenating variables to reduce the amount of characters in the variable and this works fine. The problem is when I'm trying to then extend that format, with another variable, for example a directory name (which gets passed from a different class), I'm getting confused on how to efficiently do this formatting. I'm also hitting the follow exception:

Traceback (most recent call last):
  File "some_script.py", line 12, in <module>
    import commands as cmd
  File "/var/tmp/commands.py", line 32, in <module>
    SOME_CMD = '{0} -p %s | tail -n +4 | awk \'{print \$4}\''.format(SOMETOOL)
KeyError: 'print \\$4'

How can I clean up this absolute mess, into a way that I can nicely format my commands file but also leave room for further extension when using the commands within a script.

Upvotes: 1

Views: 280

Answers (2)

user20160
user20160

Reputation: 1394

If you have a complicated line with multiple replacements, you can do something like this:

# replacements
reps = {
    'foo': 'aaa',
    'bar': 'bbb',
    'baz': 'ccc'
}

# string to format
s = '...{foo}...{bar}...{baz}...'

# format it
s2 = s.format(**reps)

# gives: '...aaa...bbb...ccc...'

Upvotes: 1

aldanor
aldanor

Reputation: 3481

If you want to use braces in formatted string, you have to escape them, e.g. in your example use

SOME_CMD = '{0} -p %s | tail -n +4 | awk \'{{print \$4}}\''.format(SOMETOOL)

-- note the double braces around print \$4.

On a related note, concatenating strings for system calls is considered a very bad practice. If you don't need shell expansion and functionality, you can use subprocess API that lets you pass arguments as lists and not strings. There's also a pretty nice sh(http://amoffat.github.io/sh/) package that supports pipes, shell expansion etc.

Upvotes: 1

Related Questions