-1

How can I call an external command (as if I'd typed it at the Unix shell) from within a Python script?

I tried this code:

from subprocess import call
call(["ls", "-l"])

and it works. But when I try this code in a Python script:

from subprocess import call
call(['sox', '/home/pi/OnoSW/data/opsoroassistant/rec.wav', '-n', 'stat', '2>&1', '|', 'sed', '-n', 's#^RMS     amplitude:[^0-9]*\([0-9.]*\)$#\1#p'])

it doesn't works. I get this error:

 sudo python getRMSAmplitude.py sox FAIL stat: Summary effect: unknown option

When I type this command in my Unix Shell:

sox ../../data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS     amplitude:[^0-9]*\([0-9.]*\)$#\1#p'

I get:

0.001754

What is correct.

Mat
  • 51
  • 1
  • 7

4 Answers4

1
call([...], shell=True)

What's happening at the moment is that the rest of the arguments you're providing, '2>&1', '|', 'sed', '-n', 's#^RMS amplitude:[^0-9]*\([0-9.]*\)$#\1#p'] are being interpreted by sox as arguments, because there isn't a shell to interpret the output redirection or the pipe. Tell call to use a shell, and it will be interpreted the same way as your command line.

Simon Fraser
  • 2,758
  • 18
  • 25
  • Thank you, Now I have no errors but when I run the script it gives no value back. The same with os.system("..."). Do I have to print it out or something? – Mat Jun 01 '16 at 11:55
  • Not sure why the downvote, but ok. No, `call` just runs the program, it doesn't return any output. You'll want `subprocess.check_output` to get whatever the process wrote to `stdout` or `stderr` into a variable. – Simon Fraser Jun 01 '16 at 12:08
  • Well I tried this: `output = subprocess.check_output(['ls', '-1']) print 'Have %d bytes in output' % len(output) print output` and I've got 99 bytes in output and the output, a list of files and dirs. and then I tried this: `output = subprocess.check_output(["sox /home/pi/OnoSW/data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS amplitude:[^0-9]*\([0-9.]*\)$#\1#p'"], shell=True) print 'Have %d bytes in output' % len(output) print output` and I've got this as output: `Have 2 bytes in output` but not the output itself. – Mat Jun 01 '16 at 13:03
  • For `call` and `check_output` and others, you either give a list containing individual elements, like `['ls', '-1']` or a string, `"ls -1"` - in your second example you have a list containing one long string. What happens when you just use the string, without it being a list? – Simon Fraser Jun 01 '16 at 13:07
  • What do you exactly mean with without it being a list? – Mat Jun 01 '16 at 13:42
  • `["sox /home/pi/OnoSW/data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS amplitude:[^0-9]*\([0-9.]*\)$#\1#p'"]` is a list containing one string. Try `"sox /home/pi/OnoSW/data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS amplitude:[^0-9]*\([0-9.]*\)$#\1#p'"` – Simon Fraser Jun 01 '16 at 13:46
  • I tried that but if I work with list or not I'm keep getting the same, it's like it gives the output but nothing is in it, here a screenshot: http://i.imgur.com/h5CUOzs.png – Mat Jun 01 '16 at 13:59
0

You can also use os.system:

import os
os.system("sox ../../data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS     amplitude:[^0-9]*\([0-9.]*\)$#\1#p'")
kaspersky
  • 3,959
  • 4
  • 33
  • 50
0

another option (easier to use) is os.system('your original command')

import os
os.system("sox ../../data/opsoroassistant/rec.wav -n stat 2>&1 | sed -n 's#^RMS     amplitude:[^0-9]*\([0-9.]*\)$#\1#p'")
Yaron
  • 10,166
  • 9
  • 45
  • 65
-2

The arguments in the call function should be in the same string as the command.

call('sed -arg1 -arg2 -argn')