My very reason for getting involved with Python was to use it as a gui for some command line programs, like eac3to, sox and neroaacenc. Previously I'd been using batch in windows and had become quite proficient.

In batch, a line to process audio with sox looks like this:

"tools\sox.exe" "name.wav" "namesox.wav" compand 0.3,1 6:-60,-50,-30 -14 -90 0.2 gain -n -1

In Python, to make it work I have to insert ' and " all over the place.

soxxy='"'+'"'+"tools\sox.exe"+'"'+' '+'"'+name+'.wav'+'"'+" "+'"'+ name+'sox.wav'+'"'+' compand 0.3,1 6:-60,-50,-30 -14 -90 0.2'+'"'

Clearly I am approaching this from the wrong direction. Could someone please point me in the correct one?
Thanks.

Dani AI

Generated

Good interventions from , and the string-formatting tips from and are right on the basics. Manually building one big quoted command works, but it’s brittle: escaping backslashes, inserting quotes for spaces, and handling errors become a pain. A more robust pattern is to let Python build an argument list and call the tool with subprocess (or Popen). That removes most manual quoting and makes error handling and GUI integration far simpler.

Example pattern (build paths with pathlib, pass a list to subprocess.run, capture output):

from pathlib import Path
import subprocess

def run_tool(name):
    exe = Path('tools') / 'sox.exe'
    infile = Path(f'{name}.wav').resolve()
    outfile = Path(f'{name}_processed.wav').resolve()
    args = [str(exe), str(infile), str(outfile), 'trim', '0', '30']  # effect parameters as separate list items
    result = subprocess.run(args, check=True, capture_output=True, text=True)   # shell=False by default
    return result.stdout

Key points and troubleshooting notes:

  • Passing a list means Python/Windows handles quoting for spaces; no need to wrap filenames in extra quotes.
  • Avoid shell=True unless shell features are required; shell=True reintroduces quoting headaches and injection risk. If a single command string is needed for logging or a shell, use subprocess.list2cmdline on Windows (or shlex.quote on POSIX) rather than hand-typing quotes.
  • For GUI apps, run the subprocess in a worker thread or use Popen and read stdout/stderr incrementally so the UI stays responsive. Catch subprocess.CalledProcessError to inspect return code and stderr when a tool fails.
  • Use pathlib or shutil.which to locate executables reliably and Path.resolve() to check paths before running.

This approach keeps code clearer, safer, and easier to debug than manually concatenating quotes and backslashes.

Recommended Answers

All 6 Replies

This should work (note the single quote at the beginning and end-Python uses both/either) but print "soxxy" to be sure.
soxxy = '"tools\sox.exe" "%s.wav" "%ssox.wav" compand 0.3,1 6:-60,-50,-30 -14 -90 0.2
gain -n -1' % (name, name)

string formatting

path = 'c:\\aPath'
arg1 = 'an argument'
arg2 = 6
'%s "%s" %s' % (path, arg1, arg2) 
# returns
'c:\\aPath "an argument" 6

%s tells python you want to insert something into the string
It replaces every occurrence of %s with what you supply it with
in the following tuple. Make sure the number of %s matches the
number of items in the tuple. It's documented here: http://docs.python.org/release/2.5.2/lib/typesseq-strings.html

Thanks guys. I have read about this but it never occured to me to use it here. The brain just needed a little push!
I'll go play...

Windows complains. It needs " at the start and end. I can do it with +'"', just did to prove it. Is there a better way?

just add the quotes where you need them in your string

'"This is a %s"' % 'test'
# returns
"This is a test"

You can add as many quotes as you like

If you need to add both single and double quotes surround your string in triple quotes, ie:

"""This 'is' a "%s" """ % 'test'
# returns
This 'is' a "test"

It is probably the blackslash which has a unique meaning in programming. Python uses a forward slash and converts depending on the OS. You can insert quotes just like any other string.

quote='"'
#  changed to a forward slash
soxxy = '%stools/sox.exe%s "%s.wav" "%ssox.wav" compand 0.3,1 6:-60,-50,-30 -14 -90 0.2 
 gain -n -1' % (quote, quote, name, name)
# etc.
print soxxy

# or use join
name = "xyz"
start_list=['"tools/sox.exe"',
           '"%s.wav"' % (name),
           '"%ssox.wav"' % (name),
           'compand 0.3,1 6:-60,-50,-30 -14 -90 0.2  gain -n -1']

print " ".join(start_list)
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.