1

I'm trying to run a shell script inside some python code, but I keep getting an error message.

Python script (test.py):

   import os
    f = os.popen('/home/test/Downloads/record.sh')
    f.close()

Shell script (record.sh):

#!/bin/sh
rec -r 16k -c 1 -p | sox -p output.wav silence 1 0.1 1% -1 0.5 1% &

When I run:

python test.py

This is the error message that I get: FAIL sox: `-' error writing output file: Broken pipe

Running the shell script alone works fine (i.e. ./record.sh).

What am I doing wrong? Thanks.

EDIT BELOW: I have changed the shell script, so it looks like this (there is no longer any piping):

#!/bin/sh
rec -r 16k -b 16 -c 1 output.wav silence 1 0.5 0.1% 1 1.0 0.1%

With Stefano's help I have the following Python script:

#!/usr/bin/python
from subprocess import Popen, PIPE
output = Popen(["sh", "/home/test/Downloads/data/recorder.sh", ], stdout=PIPE).communicate()[0]

Do I still need the PIPE and communicate bits?

What do I need to change, so that the python script doesn't wait for recorder.sh to finish before moving on?

2
  • I think this one may be more appropriate for stackoverflow.com since it's a programming question, rather than an Ubuntu question.
    – user2405
    Dec 23, 2010 at 23:40
  • Sorry if this is the wrong place. I'm using Ubuntu and thought I could ask the question here. I'll go to stackoverflow.com next time.
    – joshu
    Dec 24, 2010 at 0:21

1 Answer 1

2

To run a shell script in python 2.6, use the commands module:

import commands
status, output = commands.getstatusoutput("./script.sh")

status is now the exist status of your program, hopefully 0. The output the same as if the script were run like this:

{ cmd ; } 2>&1

In python3, the getstatusoutput method has moved into subprocess,

import subprocess
status, output = subprocess.getstatusoutput("./script.sh")

Please refer to:

In the standard library documentation.

There are more ways to spawn subprocesses, and you need to assess which one is the correct method in your case. Refer to the subprocess docs to read about them.

An even better way to run your script is this:

from subprocess import Popen, PIPE
output = Popen(["sh", "script.sh", ], stdout=PIPE).communicate()[0]

It will work in python 2.6, 2.7, 3.1 and 3.2.

Note though that you can not use shell script in this method, if you want to pipe output around, use this method instead:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Whereas the commands module will accept "dmesg | grep hda"

4
  • 1
    Stefano thanks for your answer. I'm new to Python and shell scripting, so please bear with me. I tried your suggested method just below ("An even better way to run your script is this:"), but I get an error that it can't find script.sh. When I add the full path I also get an error.
    – joshu
    Dec 24, 2010 at 0:23
  • what's the exact line? it should be Popen(["sh", "script.sh", ], stdout=PIPE).communicate()[0] - note that the command you run is "sh", with "script.sh" as an argument. the command and its arguments are given as a List, that's ["ls", "-l", ] for example Dec 24, 2010 at 0:45
  • @yonatan that's a whole different question - there are a few ways to do it, I suggest you ask it on stackoverflow - you'll get an answer in minutes. (Actually, this will have been asked before and you can just search for it) Dec 25, 2010 at 18:18
  • ok no problem will do! Thanks for all your help. Happy Holidays ;)
    – joshu
    Dec 25, 2010 at 20:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .