Search on blog:

Komendy shella w Pythonie

WERSJA ROBOCZA

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


« Page: 1 / 1 »