레거시 파이썬 스크립트에 대한 기능 테스트를 작성하여 두려움에 의해 마비되지 않고 한 줄로 변경할 수 있습니다. ;)subprocess.Popen call in Python
문제의 스크립트는 다음 (1) 구문 분석하는 XML 파일 다운로드 subprocess.Popen를 사용하여 wget을 호출 : 분명히
def download_files():
os.mkdir(FEED_DIR)
os.chdir(FEED_DIR)
wget_process = Popen(
["wget", "--quiet", "--output-document", "-", "ftp://foo.com/bar.tar"],
stdout=PIPE
)
tar_process = Popen(["tar", "xf", "-"], stdin=wget_process.stdout)
stdout, stderr = tar_process.communicate()
, 사용하는 스크립트를 수정하는 것이 바람직 할 것 wget을 실행하는 대신 HTTP 라이브러리를 사용하지만, 내가 말했던 것처럼 이것은 레거시 스크립트이므로 XML 파일을 얻는 방법과는 아무런 관련이없는 비즈니스 요구 사항에 최소한으로 초점을 맞추어야합니다.
확실한 해결책은 하위 프로세스에 대한 호출을 가로 채고,을 호출하고 내 자신의 테스트 XML을 반환하는 것입니다. 에서 (올바르게 설정되는 속성에도 불구하고, 당신이 볼 수 있듯이
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> object.__getattribute__(subprocess, 'Popen')
<class 'subprocess.Popen'>
>>> attr = object.__getattribute__(subprocess, 'Popen')
>>> hasattr(attr, '__call__')
True
>>> def foo(): print('foo')
...
>>> foo
<function foo at 0x7f8e3ced3c08>
>>> foo()
foo
>>> setattr(subprocess, '__call__', foo)
>>> getattr(subprocess, '__call__')
<function foo at 0x7f8e3ced3c08>
>>> subprocess.Popen([ r"tail", "-n 1", "x.txt" ], stdout = subprocess.PIPE)
<subprocess.Popen object at 0x7f8e3ced9cd0>
>>> tail: cannot open `x.txt' for reading: No such file or directory
은, 실제 subprocess.Popen가 호출되고 : Intercept method calls in Python이 작업을 수행 할 않은 setattr를 사용하는,하지만 난 뭔가 빠진해야하는 방법을 보여줍니다 적어도 내 숙련되지 않은 눈까지). 대화 형 파이썬이 실행이 단지 결과인가, 아니면 내 테스트 스크립트에 코드 이런 종류의 낙하 같은 결과를 기대한다 : 당신이 당신의 테스트 스크립트 대신 subprocess.Popen.__call__
의 subprocess.__call__
을 설정하지 않는
class MockProcess:
def __init__(self, output):
self.output = output
def stderr(): pass
def stdout(): return self.output
def communicate():
return stdout, stderr
# Runs script, returning output
#
def run_agent():
real_popen = getattr(subprocess.Popen, '__call__')
try:
setattr(subprocess.Popen, '__call__', lambda *ignored: MockProcess('<foo bar="baz" />')
)
return real_popen(['myscript.py'], stdout = subprocess.PIPE).communicate()[0]
finally:
setattr(subprocess.Popen, '__call__', real_popen)
그래, 그게 내 문제 중 하나 였어. 동료 덕분에 두 명을 더 찾았습니다. : -/ –
이봐 요, 지금 작동한다면, 당신은 :-), 안됩니다 : - /. ;-) BTW, 당신은 당신이 일하는 것으로 당신 자신의 질문에 대답 할 수 있습니다! – DSM
그래, 나 지금 :) 내 자아를 위해 아래를 보아라. –