[참조] https://docs.python.org/ko/3/library/subprocess.html#subprocess-replacements

파이썬, 명령 실행 함수를 subprocess 모듈로 교체하기

 

- 《a는 b가 됩니다》는 b가 a의 대체로 사용될 수 있음을 의미합니다.

- 이곳의 모든 《a》 함수는 실행되는 프로그램을 찾을 수 없으면 조용히 실패합니다; 《b》 대체는 대신 OSError를 발생시킵니다.

- 요청된 연산이 0이 아닌 반환 코드를 생성하면 check_output()을 사용한 대체는 CalledProcessError로 실패합니다. 출력은 여전히 발생한 예외의 output 어트리뷰트로 사용 가능합니다.

 

다음 예제는, 관련 함수를 subprocess 모듈에서 임포트 했다고 가정합니다.

/bin/sh 셸에 사용된 명령 치환 교체하기

output=$(mycmd myarg)

는 다음처럼 됩니다:

output = check_output(["mycmd", "myarg"])

셸 파이프라인 교체하기

output=$(dmesg | grep hda)

는 다음처럼 됩니다:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

p2가 p1보다 먼저 종료될 때 p1이 SIGPIPE 수신하려면 p2 시작한 후 p1.stdout.close() 호출하는 것이 중요합니다.

또는, 신뢰할 수 있는 입력의 경우, 셸의 자체 파이프라인 지원을 계속 사용할 수 있습니다:

output=$(dmesg | grep hda)

는 다음처럼 됩니다:

output = check_output("dmesg | grep hda", shell=True)

os.system() 교체하기  

sts = os.system("mycmd" + " myarg")
# becomes
retcode = call("mycmd" + " myarg", shell=True)

  보통 셸을 통해 프로그램을 호출할 필요는 없습니다.

  • The call() return value is encoded differently to that of os.system().
  • The os.system() function ignores SIGINT and SIGQUIT signals while the command is running, but the caller must do this separately when using the subprocess module.

현실적인 예는 다음과 같습니다:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print("Child was terminated by signal", -retcode, file=sys.stderr)
    else:
        print("Child returned", retcode, file=sys.stderr)
except OSError as e:
    print("Execution failed:", e, file=sys.stderr)

os.spawn 패밀리 교체하기

P_NOWAIT 예:

pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid

P_WAIT 예:

retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])

벡터 예:

os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])

환경 예:

os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})

os.popen(), os.popen2(), os.popen3() 교체하기

(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
 child_stdout,
 child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
 child_stdout,
 child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

반환 코드 처리는 다음과 같이 번역됩니다:

pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
    print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
    print("There were some errors")

popen2 모듈의 함수 교체하기

참고

popen2 함수에 대한 cmd 인자가 문자열이면, 명령은 /bin/sh 를 통해 실행됩니다. 리스트면, 명령이 직접 실행됩니다.

(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen("somestring", shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)

popen2.Popen3 popen2.Popen4는 다음과 같은 점을 제외하고는 기본적으로 subprocess.Popen처럼 작동합니다:

  • 실행이 실패하면 Popen은 예외를 발생시킵니다.
  • capturestderr 인자는 stderr 인자로 대체됩니다.
  • stdin=PIPE stdout=PIPE를 반드시 지정해야 합니다.
  • popen2는 기본적으로 모든 파일 기술자를 닫지만, 모든 플랫폼이나 이전 파이썬 버전에서 이 동작을 보장하려면 Popen close_fds=True를 지정해야 합니다.

레거시 셸 호출 함수

이 모듈은 2.x commands 모듈의 다음과 같은 레거시 함수도 제공합니다. 이러한 연산은 시스템 셸을 묵시적으로 호출하고 보안과 예외 처리 일관성과 관련하여 위에서 설명한 보증 중 어느 것도 이러한 함수에 유효하지 않습니다.

subprocess.getstatusoutput(cmd)

셸에서 cmd를 실행한 후 (exitcode, output)을 반환합니다.

Popen.check_output()으로 셸에서 문자열 cmd를 실행하고 2-튜플 (exitcode, output)을 반환합니다. 로케일 인코딩이 사용됩니다; 자세한 내용은 자주 사용되는 인자에 대한 참고 사항을 참조하십시오.

후행 줄 바꿈이 출력에서 제거됩니다. 명령의 종료 코드는 서브 프로세스의 반환 코드로 해석될 수 있습니다. 예:

>>>
>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
>>> subprocess.getstatusoutput('cat /bin/junk')
(1, 'cat: /bin/junk: No such file or directory')
>>> subprocess.getstatusoutput('/bin/junk')
(127, 'sh: /bin/junk: not found')
>>> subprocess.getstatusoutput('/bin/kill $$')
(-15, '')

가용성: POSIX & 윈도우.

버전 3.3.4에서 변경: 윈도우 지원이 추가되었습니다.

이 함수는 이제 파이썬 3.3.3과 이전 버전에서와같이 (status, output) 대신 (exitcode, output) 을 반환합니다. exitcode는 returncode와 같은 값을 갖습니다.

subprocess.getoutput(cmd)

셸에서 cmd를 실행한 출력(stdout과 stderr)을 반환합니다.

종료 코드를 무시하고 반환 값은 명령의 출력을 포함하는 문자열인 것을 제외하고, getstatusoutput() 과 유사합니다. 예:

>>>
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'

가용성: POSIX & 윈도우.

버전 3.3.4에서 변경: 윈도우 지원이 추가되었습니다

노트

윈도우에서 인자 시퀀스를 문자열로 변환하기

윈도우에서, args 시퀀스는 다음 규칙을 사용하여 구문 분석할 수 있는 문자열로 변환됩니다 (MS C 런타임에서 사용하는 규칙에 해당합니다):

  1. 인자는 스페이스나 탭인 공백으로 구분됩니다.
  2. 큰따옴표로 묶인 문자열은 포함된 공백과 관계없이 단일 인자로 해석됩니다. 인용된 문자열을 인자에 포함할 수 있습니다.
  3. 백 슬래시가 앞에 붙는 큰따옴표는 리터럴 큰따옴표로 해석됩니다.
  4. 역 슬래시는 큰따옴표 바로 앞에 오지 않는 한 문자 그대로 해석됩니다.
  5. 역 슬래시가 큰따옴표 바로 앞에 있으면, 모든 역 슬래시 쌍은 리터럴 역 슬래시로 해석됩니다. 역 슬래시 수가 홀수이면, 규칙 3에 설명된 대로 마지막 역 슬래시는 다음 큰따옴표를 이스케이프 합니다.

 

반응형

+ Recent posts