
Python je multiplatformní jazyk oblíbený pro svou jednoduchost a stručnost. Jeho hlavní předností je srozumitelná a čistá syntaxe. Díky své jednoduchosti bývá označován jako jeden z nejvhodnějších programovacích jazyků pro začátečníky.
Hlavní funkcí, kterou bychom měli pro spouštění sheelových příkazů používat v Pythonu subprocess.run(). Ale než se k ní dostaneme, je vhodné začít funkcí subprocess.Popen, u které narozdíl od prvního příkazu můžeme používat shellovou pipe.
Jde si všimnout, že v příkazu subprosses se používá stdout a stderr s PIPE. Pipe pak jde číst příkazem .communicate().
import subprocess
process = subprocess.Popen(['echo', 'More output'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout, stderr)
Výstupem bude:
(b'More output\n', b'')
Stdout jde použít i bez pipe například pro ukládání do souboru:
with open('test.txt', 'w') as f:
process = subprocess.Popen(['ls', '-l'], stdout=f)
Co nejspíš čtenář zaznamenal je to, že výstup příkazů z output je typu bytes. To lze řešit například překodováním do utf-8 pomocí stdout.decode('utf-8') nebo přidáním universal_newlines=True, když voláme subprocess.Popen.
Pokud máme program, kde periodicky obnovujeme status v běhu programu, můžeme to řešit while cyklem a pomocí funkce .poll(), která kontroluje návratový status příkazu.
process = subprocess.Popen(['ping', '-c 4', 'python.org'],
stdout=subprocess.PIPE,
universal_newlines=True)
while True:
output = process.stdout.readline()
print(output.strip())
# Do something else
return_code = process.poll()
if return_code is not None:
print('RETURN CODE', return_code)
# Process has finished, read rest of the output
for output in process.stdout.readlines():
print(output.strip())
break
V případě, že proces vrací None, pokračuje se v běhu. O přečtení jednoho řádku se stará process.stdout.readline(), o přečtění všech řádků po dokončení procesu process.stdout.readlines():
PING python.org (45.55.99.72) 56(84) bytes of data.
64 bytes from 45.55.99.72 (45.55.99.72): icmp_seq=1 ttl=51 time=117 ms
64 bytes from 45.55.99.72 (45.55.99.72): icmp_seq=2 ttl=51 time=118 ms
64 bytes from 45.55.99.72 (45.55.99.72): icmp_seq=3 ttl=51 time=117 ms
64 bytes from 45.55.99.72 (45.55.99.72): icmp_seq=4 ttl=51 time=118 ms
--- python.org ping statistics ---
RETURN CODE 0
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 117.215/117.874/118.358/0.461 ms
Subprocess.run() je doporučovaný způsob jak spouštět jeden příkaz, u kterého stačí prosté vyčkávání na jeho dokončení:
process = subprocess.run(['echo', 'Even more output'],
stdout=subprocess.PIPE,
universal_newlines=True)
print(process)
Output je tento:
CompletedProcess(args=['echo', 'Even more output'], returncode=0, stdout='Even more output\n')
Někdy chceme s programem komunikovat a interaktivně zadávat něco na vstup. Příklad ukazuje, že i toto lze velice jednoduše řešit.
import subprocess
ssh = subprocess.Popen(["ssh", "-i .ssh/id_rsa", "user@host"],
stdin =subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
bufsize=0)
# Send ssh commands to stdin
ssh.stdin.write("uname -a\n")
ssh.stdin.write("uptime\n")
ssh.stdin.close()
# Fetch output
for line in ssh.stdout:
print(line.strip())