Reputation: 9833
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
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
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