Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

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?

share|improve this question
    
I think this one may be more appropriate for stackoverflow.com since it's a programming question, rather than an Ubuntu question. –  Chris Wilson Dec 23 '10 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 '10 at 0:21
add comment

1 Answer 1

up vote 2 down vote accepted

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"

share|improve this answer
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 '10 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 –  Stefano Palazzo Dec 24 '10 at 0:45
    
please see my edit in my original post. Thanks –  joshu Dec 25 '10 at 14:37
    
@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) –  Stefano Palazzo Dec 25 '10 at 18:18
    
ok no problem will do! Thanks for all your help. Happy Holidays ;) –  joshu Dec 25 '10 at 20:12
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.