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()
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 :)