hidura
hidura

Reputation: 693

How to use subprocess to execute programs with Python

Hello i am using the subprocess.Popen() class and i succesful execute commands on the terminal, but when i try to execute programs for example an script written on Python and i try to pass arguments the system fails.

This is the code:

            argPath = "test1"
            args = open(argPath, 'w')

            if self.extract.getByAttr(self.block, 'name', 'args') != None:
                args.write("<request>"+self.extract.getByAttr(self.block, 'name', 'args')[0].toxml()+"</request>")
            else:
                args.write('')

            car = Popen(shlex.split('python3.1 /home/hidura/webapps/karinapp/Suite/ForeingCode/saveCSS.py', stdin=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE))
            args.close()

            dataOut = car.stdout.read().decode()
            log = car.stderr.read().decode()


            if dataOut!='':
                return dataOut.split('\n')

            elif log != '':
                return log.split('\n')[0]

            else:
                return None

And the code from the saveCSS.py

from xml.dom.minidom import parseString
import os
import sys

class savCSS:
        """This class has to save

    the changes on the css file.
    """

    def __init__(self, args):

        document = parseString(args)
        request = document.firstChild

        address = request.getElementsByTagName('element')[0]
        newdata = request.getElementsByTagName('element')[1]

        cssfl = open("/webapps/karinapp/Suite/"+address.getAttribute('value'), 'r')
        cssData = cssfl.read()
        cssfl.close()

        dataCSS = ''
        for child in newdata.childNodes:
            if child.nodeType == 3:
                dataCSS += child.nodeValue

        nwcssDict = {}

        for piece in dataCSS.split('}'):
            nwcssDict[piece.split('{')[0]] = piece.split('{')[1]


        cssDict = {}

        for piece in cssData.split('}'):
            cssDict[piece.split('{')[0]] = piece.split('{')[1]


        for key in nwcssDict:
            if key in cssDict == True:
                del cssDict[key]

            cssDict[key] = nwcssDict[key]


        result = ''
        for key in cssDict:
            result += key+"{"+cssDict[key]+"}"


        cssfl = open(cssfl.name, 'a')
            cssfl.write(result)
            cssfl.close()



if __name__ == "__main__":
    savCSS(sys.stdin)

BTW: There's no output...

Thanks in advance.

Upvotes: 1

Views: 787

Answers (2)

Lennart Regebro
Lennart Regebro

Reputation: 172367

OK, I'm ignoring that your code doesn't run (neither the script you try to execute, not the main script actually works), and looking at what you are doing:

It does execute the script, or you would get an error, like "bin/sh: foo: not found".

Also you seem to be using an open file as stdin after you have written to it. That doesn't work.

>>> thefile = open('/tmp/foo.txt', 'w')
>>> thefile.write("Hej!")
4
>>> thefile.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: not readable

You need to close the file, and reopen it as a read file. Although better in this case would be to use StringIO, I think.

To talk to the subprocess, you use communicate(), not read() on the pipes.

I'm not sure why you are using shell=True here, it doesn't seem necessary, I would remove it if I was you, it only complicates stuff unless you actually need the shell to do things. Specifically you should not split the command into a list when using shell=True. What your code is actually doing, is starting a Python prompt.

Upvotes: 3

AndiDog
AndiDog

Reputation: 70228

You should rather use communicate() instead of .stdout.read().

And the code you posted isn't even correct:

Popen(shlex.split('python3.1 /home/hidura/webapps/karinapp/Suite/ForeingCode/saveCSS.py', stdin=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

There's a missing parenthesis, and from the stdout/stderr parameters, it's clear that you get no output to the console, but rather into pipes (if that's what you meant by "There's no output...").

Your code will actually work on Windows, but on Linux you must remove the shell=True parameter. You should always omit that parameter if you provide the full command line yourself (as a sequence).

Upvotes: 2

Related Questions