Komendy shella w Pythonie
os.system()
Funkcja jest zawarta w standardowym module Pythona więc nie trzeba nic doinstalowywać.
import os
os.system('ls')
os.system('ls -l')
W łatwy sposób można uruchomić zewnętrzny program ale nie sposób przechwycić wyświetlanych wyników aby je obrobić w Pythonie. Można jedynie przekierować do pliku, który następnie się czyta
import os
os.system('ls > output.txt')
wynik = open('output.txt').read()
Przekierowanie można też użyć do ukrycia wyświetlanych wyników. Pod Linux można przekierować do /dev/null
os.system('ls > /dev/null')
Ponieważ jest to przekazywane do shella/powłoki więc można stosować potokowanie
os.system('ls | sort -r | head')
Kiedyś w dokumentacji dla Python 2 można było wyczytać, że funkcja ta jest przestarzała/niezalecana (ang. deprecated) i może zostać usunięta w kolejnych wersjach ale przez lata nigdy nie zniknęła za to gdzieś przepadła informacja, że funkcja jest przestarzała.
Dokumenatacja: os.system(command)
os.startfile()
Dostępna tylko w Windows, którego nie używam.
Dokumenatacja: os.startfile(path[, operation])
os.spawn()
Dokumenatacja: os.spawn()
os.popen()
https://docs.python.org/3/library/os.html#os.popen
Używa subprocess.Popen()
os.exec()
Moduł shlex
Moduł shlex jest przydatny do podziału tekstu z komendą na listę wymaganą przez niektóre funkcje.
Szczególnie przydatna gdy komenda zawiera kilka wyrazów w cudzysłowie, które nie powinny być podzielone na osobne elementy na liście
import shlex
output = shutil.split('cat "new name.txt"')
print(output)
Zamienia cat "new name.txt"
na ['cat', '"new name.txt"']
a nie ['cat', '"new', 'name.txt"']
(jak dla w 'cat "new name.txt"'.split(' ')
Moduł subprocess
Dokumentacja: subprocess Standardowy moduł
subprocess.run()
dostępne od Python 3.5. W 3.6 dodano opcje encoding
, errors
a w 3.7 text
i capture_output
.
W dokumentacji jest opisane (po angielsku) jak zastąpić inne komendy za pomocą subprocess
Moduł sh
Moduł sh pozwala na łatwe wykonywanie komend shell
$ ls
import sh
sh.ls()
$ date
sh.date()
$ ifconfig
sh.date()
$ ls -l
sh.ls("-l")
Potokowanie
$ cat '/etc/passwd' | sort
import sh
sh.sort(sh.cat('/etc/passwd'))
$ ls -l | sort
sh.sort(sh.ls('-l'))
$ ls -l | sort -r
sh.sort(sh.ls('-l'), '-r')
Potokowanie zaczyna być nieczytelne przy wielu przekierowaniach
$ ls -l | grep ^d | sort -r
sh.sort(sh.grep(sh.ls('-l'), '^d'), '-r')
Przekierowanie do pliku:
$ ls -1 | sort -r > output.txt
sh.sort(sh.ls("-1"), '-r', _out='output.txt')
Przekierowanie do pliko-podobnego obiektu StringIO
from io import StringIO
mem = StringIO()
sh.sort(sh.ls("-1"), '-r', _out=mem)
Komendy zwracają tekst więc można wykonywac działania tekstowe
sh.pwd()
sh.pwd().strip().split('/')
sh.pwd().strip().strip('/').split('/')
sh.pwd().strip()[1:].split('/')
Tekst zwracany przez komendę można też obsługiwać linia po linii
for line in sh.ls():
print('>', line.strip())
::::python
for line in sh.env():
line = line.rstrip() # usuniecie '\n' z konca linii
key, val = line.split('=', 1) # niektóre linie mogą mieć więcej niż jeden `=`
print(key, '=>', val)
Czego nie ma
Nie ma wszelkich elementów obsługiwanych bezpośrednio przez Bash
lub inny shell.
Nie można wywołać aliasu
sh.ll() # `ll` alias dla `ls -al`
# error
sh.alias()
# error
Ale można stworzyć własne
ll = sh.ls.bake('-l')
ll()
ll('-a')
Nie ma rozwijania nazw plików zawierających *
i/lub ?
sh.cat('/etc/pass*')
# error
Nie ma historii Bash
sh.history()
# error
Nie ma rozwijania zmiennych środowiskowych
sh.echo('$HOME')
# $HOME
sh.echo('~')
# ~
sh.ls('$HOME')
# error
sh.ls('~')
# error
Nie ma potokowania za pomocą |
sh.ls("-l") | sh.sort('-r')
Nie ma przekierowania za pomocą >
sh.ls("-l") > 'output.txt'
Niektóre z tych rzeczy są dostępne w module plumbum
Podobne