Python Forum

Full Version: shell script inside python
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
I am trying to generate a shell script inside the python script and then planning to execute it. I know that this is a very naive way. This snippet works. Is there a better way to handle this?Thanks.

        cmd1 = "git clone repoName" + '\n'
        cmd2 = "cd repoName" + '\n'
        cmd3 = "git checkout version" + '\n'
        fh = open(shell_script, 'w')
        fh.write(cmd1)
        fh.write(cmd2)
        fh.write(cmd3)
        fh.close()
Well, I was using subprocess for this. Most people use it too so there is probably reason why.

Example: https://stackoverflow.com/questions/5702...rom-python
One approach can be:

import subprocess
import textwrap
import sys
import tempfile


def make_command(repo_name, branch='master'):
    cmd = """
          git clone {0}
          cd {1}
          git checkout {2}
          """
    parent, sep, directory = repo_name.rpartition('/')
    directory = directory.replace('.git', '')
    return textwrap.dedent(
        cmd.format(repo_name, directory, branch)
        ).strip()


def main():
    if len(sys.argv) != 2:
        print(sys.argv[0], 'git-respository.git [branch]')
        sys.exit(1)
    if len(sys.argv) == 3:
        branch = sys.argv[2]
    else:
        branch = 'master'
    respository = sys.argv[1]
    cmd = make_command(respository, branch)
    with tempfile.TemporaryFile(mode='r+') as tmp:
        tmp.write(cmd)
        tmp.seek(0)
        subprocess.Popen(['/bin/sh'], stdin=tmp)


if __name__ == '__main__':
    main()
Ask, if you don't understand it.
(Sep-04-2018, 09:39 AM)DeaD_EyE Wrote: [ -> ]
import subprocess
....
    with tempfile.TemporaryFile(mode='r+') as tmp:
        tmp.write(cmd)
        tmp.seek(0)
        subprocess.Popen(['/bin/sh'], stdin=tmp)
....
Interesting.

One question - why didn't you just use io.StringIO (or io.ByteIO) as a temp file?
Quote:One question - why didn't you just use io.StringIO (or io.ByteIO) as a temp file?

Yes, a BytesIO or StringIO is better in this case. A real file is not needed.

My first thought was, call the shellscript with /bin/bash or /bin/sh (/bin/dash on Debian).
This needs a real file. Then I saw that the shell accepts input from stdin.

You can replace Line 30 with:
with io.StringIO() as tmp:
Unexpectedly StringIO also has also a context manager.
Don't forget to import io.
The module tempfile is no longer needed and should be removed from imports.
(Sep-04-2018, 02:42 PM)DeaD_EyE Wrote: [ -> ]Unexpectedly StringIO also has also a context manager.

Nothing unexpected about that - file objects and stream objects share common base class, see io module doc

Output:
In [32]: file_obj = open('fb_formatter.py') In [33]: file_obj.__class__, file_obj.__class__.__base__ Out[33]: (_io.TextIOWrapper, _io._TextIOBase) In [34]: stream_obj = io.StringIO('This is a stream') In [35]: stream_obj.__class__, stream_obj.__class__.__base__ Out[35]: (_io.StringIO, _io._TextIOBase)
Thanks everyone. I will take it from here :)