Czytałem dokumentację Pythona o module podprocesu (patrz tutaj ) i mówi o subprocess.check_output()
poleceniu, które wydaje się być dokładnie tym, czego potrzebuję.
Jednak kiedy próbuję go użyć, pojawia się błąd, że nie istnieje, a kiedy dir(subprocess)
go uruchamiam, nie ma go na liście.
Używam Pythona 2.6.5, a kod, którego użyłem, jest poniżej:
import subprocess
subprocess.check_output(["ls", "-l", "/dev/null"])
Czy ktoś ma pojęcie, dlaczego tak się dzieje?
CalledProcessError
gdy proces zwraca niezerowy kod powrotu.lambda
ten sposób:check_output = lambda args: Popen(args, stdout = PIPE).communicate()[0]
. Tylko dlatego, że jestem w interaktywnym tłumaczu i zapisywanie w nich definicji funkcji wielowierszowych jest czymś w rodzaju PITA. Użyłemfrom subprocess import Popen, PIPE
wcześniej w sesji.JEŚLI jest intensywnie używany w kodzie, który chcesz uruchomić, ale ten kod nie musi być utrzymywany przez długi czas (lub potrzebujesz szybkiej naprawy niezależnie od potencjalnych problemów związanych z konserwacją w przyszłości), możesz uchylić się przed uderzeniem (inaczej łatka małpa) wszędzie tam, gdzie importowany jest podproces ...
Po prostu podnieś kod z 2.7 i wstaw go w ten sposób ...
import subprocess if "check_output" not in dir( subprocess ): # duck punch it in! def f(*popenargs, **kwargs): if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise subprocess.CalledProcessError(retcode, cmd) return output subprocess.check_output = f
Może być wymagane lekkie wiercenie się.
Pamiętaj, że to na tobie spoczywa obowiązek utrzymania takich brudnych, małych backportów. Jeśli błędy zostaną wykryte i poprawione w najnowszym Pythonie, to a) musisz to zauważyć i b) zaktualizować swoją wersję, jeśli chcesz zachować bezpieczeństwo. Ponadto, samodzielne nadpisywanie i definiowanie funkcji wewnętrznych jest najgorszym koszmarem następnego faceta, zwłaszcza gdy następny facet jest TY kilka lat później i zapomniałeś o wstrętnych hackach, które zrobiłeś ostatnim razem! Podsumowując: bardzo rzadko jest to dobry pomysł.
źródło
check_output
dla Pythona 2.7 jest obecnie tutaj: github.com/python/cpython/blob/2.7/Lib/subprocess.py#L194Dzięki sugestii małpy dotyczącej łatki (i moim próbom się nie powiodło - ale korzystaliśmy z wyjścia CalledProcessError, więc potrzebowaliśmy małpy to załatać)
znalazłem działającą łatkę 2.6 tutaj: http://pydoc.net/Python/pep8radius/0.9.0/pep8radius.shell/
"""Note: We also monkey-patch subprocess for python 2.6 to give feature parity with later versions. """ try: from subprocess import STDOUT, check_output, CalledProcessError except ImportError: # pragma: no cover # python 2.6 doesn't include check_output # monkey patch it in! import subprocess STDOUT = subprocess.STDOUT def check_output(*popenargs, **kwargs): if 'stdout' in kwargs: # pragma: no cover raise ValueError('stdout argument not allowed, ' 'it will be overridden.') process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) output, _ = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise subprocess.CalledProcessError(retcode, cmd, output=output) return output subprocess.check_output = check_output # overwrite CalledProcessError due to `output` # keyword not being available (in 2.6) class CalledProcessError(Exception): def __init__(self, returncode, cmd, output=None): self.returncode = returncode self.cmd = cmd self.output = output def __str__(self): return "Command '%s' returned non-zero exit status %d" % ( self.cmd, self.returncode) subprocess.CalledProcessError = CalledProcessError
źródło