나는 subprocess 모듈에 관한 파이썬 문서를 읽고 있었는데 ( 여기를보세요 ) subprocess.check_output()
정확히 내가 필요한 것처럼 보이는 명령 에 대해 이야기 합니다.
그러나 그것을 시도하고 사용하면 존재하지 않는다는 오류가 발생하고 실행 dir(subprocess)
하면 나열되지 않습니다.
Python 2.6.5를 실행하고 있으며 사용한 코드는 다음과 같습니다.
import subprocess
subprocess.check_output(["ls", "-l", "/dev/null"])
왜 이런 일이 일어나는지 아는 사람이 있습니까?
답변
2.7에서 도입되었습니다 . 문서를 참조하십시오 .
출력을 원하면 subprocess.Popen을 사용하십시오 .
>>> import subprocess
>>> output = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
답변
경우 당신이 실행하려는 코드를 많이 사용하지만 사용자들은 코드가 장기적으로 유지 될 필요가 없다 (또는 미래에 관계없이 잠재적 인 유지 보수 두통의 빠른 수정이 필요) 다음 수 오리 펀치 (원숭이 패치 일명) 하위 프로세스를 가져올 때마다 …
2.7에서 코드를 들어 올려 삽입하면됩니다.
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
약간의 안절부절이 필요할 수 있습니다.
이와 같이 더럽고 작은 백 포트를 유지해야 할 책임이 있음을 명심하십시오. 최신 파이썬에서 버그가 발견되고 수정되면 a)이를인지하고 b) 보안을 유지하려면 버전을 업데이트해야합니다. 또한 내부 함수를 직접 재정의하고 정의하는 것은 다음 사람에게 최악의 악몽입니다. 특히 다음 사람이 몇 년 후 당신이고 지난번에했던 그 로디 해킹에 대해 모두 잊어 버린 경우! 요약하면 아주 드물게 좋은 생각입니다.
답변
원숭이 패치 제안 덕분에 (내 시도는 실패했지만 우리는 CalledProcessError 출력을 소비하고 있었기 때문에 원숭이 패치가 필요했습니다)
여기에서 작동하는 2.6 패치를 찾았습니다 :
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