Python Shell Chapter2 PDF
Python Shell Chapter2 PDF
commands in
subprocess
C O M M A N D L I N E A U TO M AT I O N I N P Y T H O N
Noah Gift
Lecturer, Northwestern & UC Davis & UC
Berkeley | Founder, Pragmatic AI Labs
Using subprocess.run
Simplest way to run shell commands using Python 3.5+
subprocess.run(["ls", "-l"])
res = b'repl 24 0.0 0.0 36072 3144 pts/0 R+ 03:15 0:00 ps aux\n'
print(type(res))
bytes
regular_string = res.decode("utf-8")
'repl 24 0.0 0.0 36072 3144 pts/0 R+ 03:15 0:00 ps aux\n'
print(type(regular_string))
ls -l
echo $?
0
ls --bogus-flag
echo $?
1
CompletedProcess object
subprocess.CompletedProcess
print(out.returncode)
0
good_user_input = "-l"
out = run(["ls", good_user_input])
if out.returncode == 0:
print("Your command was a success")
else:
print("Your command was unsuccesful")
Noah Gift
Lecturer, Northwestern & UC Davis & UC
Berkeley | Founder, Pragmatic AI Labs
Using the subprocess.Popen module
Captures the output of shell commands
bash-3.2$ ls
some_file.txt some_other_file.txt
['some_file.txt','some_other_file.txt']
proc = subprocess.Popen(...)
# Attempt to communicate for up to 30 seconds
try:
out, err = proc.communicate(timeout=30)
except TimeoutExpired:
# kill the process since a timeout was triggered
proc.kill()
# capture both standard output and standard error
out, error = proc.communicate()
One intuition about PIPE is to think of it as tube that connect to other tubes
shell=False
is default and recommended
# Unsafe!
with Popen("ls -l /tmp", shell=True, stdout=PIPE) as proc:
stderr output
[b'bar.txt\n', b'foo.txt\n']
b'bar.txt'
b'foo.txt'
Noah Gift
Lecturer, Northwestern & UC Davis & UC
Berkeley | Founder, Pragmatic AI Labs
Using Unix Pipes as input
Two ways of connecting input
Popen method
ls -l
total 160
-rw-r--r-- 1 staff staff 13 Apr 15 06:56
-rw-r--r-- 1 staff staff 12 Apr 15 06:56 file_9.txt
ls | wc
20 20 220
methods
often columnar
Subprocess can pipe input to scripts that wait for user input.
Noah Gift
Lecturer, Northwestern & UC Davis & UC
Berkeley | Founder, Pragmatic AI Labs
User input is unpredictable
Expected input to a script
"/some/dir"
#shell=False is default
run(["ls", "-l"],shell=False)
directory = shlex.split("/tmp")
cmd = ["ls"]
cmd.extend(directory)
run(cmd, shell=True)
Limits mistakes
Reduce complexity