[python] 쉘 명령을 직접 실행하는 대신 Python의 os 모듈 메소드를 사용하는 이유는 무엇입니까?

나는 그런 파일 / 디렉토리를 생성하는 파일 속성을 변경하는 등 대신에 단지를 통해 해당 명령을 실행으로 OS 특정 작업을 실행하기위한 파이썬 라이브러리 함수를 사용하여 뒤에있는 동기 부여 무엇을 이해하려고 os.system()하거나 subprocess.call()?

예를 들어 왜하지 os.chmod않고 사용 하고 os.system("chmod...")싶습니까?

쉘 명령을 직접 실행하는 대신 가능한 파이썬의 라이브러리 메소드를 최대한 많이 사용하는 것이 “파이썬”이라는 것을 이해합니다. 그러나 기능적 관점에서이 작업을 수행하는 데 다른 동기가 있습니까?

여기서는 간단한 한 줄 쉘 명령 실행에 대해서만 이야기하고 있습니다. 우리는 작업 실행에 대한 더 많은 제어가 필요할 때 subprocess예를 들어 모듈 을 사용 하는 것이 더 의미가 있음을 이해합니다 .



답변

  1. 그건 더 빨리 , os.system그리고 subprocess.call일이 간단한에 대한 필요는 새로운 프로세스를 생성합니다. 사실, os.system그리고 subprocess.callshell쉘되는 첫 번째, 그리고 (가 내장 같은 쉘이 아니라면 실행중인 것을 명령 인 두 번째 : 인수 일반적으로 두 개 이상의 새로운 프로세스를 생성 test).

  2. 일부 명령은 별도의 프로세스에서 쓸모없습니다 . 예를 들어을 실행 os.spawn("cd dir/")하면 자식 프로세스의 현재 작업 디렉토리가 변경되지만 Python 프로세스는 변경되지 않습니다. 당신은 그것을 사용해야 os.chdir합니다.

  3. 쉘이 해석 하는 특수 문자 에 대해 걱정할 필요가 없습니다 . os.chmod(path, mode)파일 이름이 무엇이든간에 작동하지만 os.spawn("chmod 777 " + path)파일 이름이과 같은 경우 끔찍하게 실패 ; rm -rf ~합니다. 인수 subprocess.call없이 사용하면이 문제를 해결할 수 있습니다 shell.

  4. 대시로 시작하는 파일 이름 에 대해 걱정할 필요가 없습니다 . os.chmod("--quiet", mode)는 파일 이름의 권한을 변경 --quiet하지만 인수로 해석되므로 os.spawn("chmod 777 --quiet")실패 --quiet합니다. 이것도 마찬가지입니다 subprocess.call(["chmod", "777", "--quiet"]).

  5. 파이썬의 표준 라이브러리가 당신을 위해 처리해야하기 때문에 크로스 플랫폼 과 크로스 셸 문제 가 적습니다 . 시스템에 chmod명령이 있습니까? 설치되어 있습니까? 지원할 것으로 예상되는 매개 변수를 지원합니까? os이 불가능하다고 할 때 모듈은 가능한 크로스 플랫폼 및 문서로 일하려고합니다.

  6. 실행중인 명령에 관심있는 출력 이있는 경우, 코너 케이스 (공백, 탭 및 줄 바꿈이있는 파일 이름)를 잊어 버릴 수 있으므로 소리보다 까다로워 야합니다. 이식성에 신경 쓰지 마십시오.


답변

더 안전합니다. 여기에 아이디어를 제공하는 예제 스크립트가 있습니다.

import os
file = raw_input("Please enter a file: ")
os.system("chmod 777 " + file)

사용자의 입력 인 경우 test; rm -rf ~홈 디렉토리가 삭제됩니다.

이것이 내장 기능을 사용하는 것이 더 안전한 이유입니다.

따라서 시스템 대신 하위 프로세스를 사용해야하는 이유는 무엇입니까?


답변

명령을 실행할 때 또는 os모듈을 사용 하는 것보다 모듈 에서 Python의보다 구체적인 메소드를 선호하는 경우가 4 가지 있습니다 .os.systemsubprocess

  • 중복성 -다른 프로세스를 생성하는 것은 중복되며 시간과 자원을 낭비합니다.
  • 이식성os모듈 의 많은 메소드는 여러 플랫폼에서 사용 가능하지만 많은 쉘 명령은 운영 체제마다 다릅니다.
  • 결과 이해 -임의의 명령을 실행하기 위해 프로세스를 생성하면 출력 결과를 구문 분석하고 명령이 잘못한 이유이유를 이해해야 합니다 .
  • 안전 -프로세스는 주어진 명령을 실행할 수 있습니다. 이것은 약한 디자인이며 os모듈 에서 특정 방법을 사용하면 피할 수 있습니다 .

이중화 ( 중복 코드 참조 ) :

실제로 최종 시스템 호출 ( chmod예 :)로가는 도중에 중복 “중간자”를 실행하고 있습니다. 이 중개인은 새로운 프로세스 또는 하위 셸입니다.

보낸 사람 os.system:

서브 쉘에서 명령 (문자열)을 실행합니다 …

그리고 subprocess산란 새로운 프로세스에 불과 모듈입니다.

이러한 프로세스를 생성하지 않고도 필요한 것을 수행 할 수 있습니다.

이식성 ( 소스 코드 이식성 참조 ) :

os모듈의 목표는 일반적인 운영 체제 서비스를 제공하는 것이며 그 설명은 다음으로 시작합니다.

이 모듈은 운영 체제 종속 기능을 사용하는 이식 가능한 방법을 제공합니다.

os.listdir윈도우와 유닉스 모두에서 사용할 수 있습니다 . 이 기능에 os.system/ 를 사용하려고하면 subprocess두 개의 통화 ( ls/ dir) 를 유지 관리 하고 사용중인 운영 체제를 확인해야합니다. 이것은 이식성이 없으며 나중에 더 많은 좌절 일으킬 입니다 ( 출력 처리 참조 ).

명령 결과 이해 :

디렉토리에 파일을 나열하려고한다고 가정하십시오.

os.system("ls")/를 사용하는 경우 subprocess.call(['ls'])프로세스의 출력 만 다시 가져올 수 있습니다. 기본적으로 파일 이름이있는 큰 문자열입니다.

파일 이름에 공백이있는 파일을 두 파일에서 어떻게 알 수 있습니까?

파일을 나열 할 권한이 없으면 어떻게합니까?

데이터를 파이썬 객체에 어떻게 매핑해야합니까?

이것들은 내 머리 꼭대기에 있으며이 문제에 대한 해결책이 있지만 왜 당신을 위해 해결 된 문제를 다시 해결합니까?

이것은 이미 존재하며 자유롭게 사용할 수있는 구현을 반복 하지 않음 으로써 자신을 반복하지 않음 원칙 (종종 “건조”라고 함) 을 따르는 예입니다 .

안전:

os.system하고 subprocess강력하다. 이 힘이 필요할 때는 좋지만, 그렇지 않을 때는 위험합니다. 당신이 사용하는 경우 os.listdir, 당신은 알고 그것을 어떤 다른 다른 다음 목록 파일을하거나 오류를 발생시킬 수 없습니다. 동일한 동작 을 사용 os.system하거나 subprocess달성 할 때 의도하지 않은 작업을 수행 할 수 있습니다.

주입 안전 ( 쉘 주입 예 참조 ) :

사용자의 입력을 새 명령으로 사용하는 경우 기본적으로 쉘을 제공합니다. 이것은 사용자를 위해 DB에 쉘을 제공하는 SQL 주입과 매우 유사합니다.

예를 들면 다음과 같은 형식의 명령이 있습니다.

# ... read some user input
os.system(user_input + " some continutation")

이것은 쉽게 실행하는 데 악용 될 수 있는 다음 입력을 사용하여 임의의 코드를 NASTY COMMAND;#최종를 만들 :

os.system("NASTY COMMAND; # some continuation")

시스템을 위험에 빠뜨릴 수있는 명령이 많이 있습니다.


답변

간단한 이유로-쉘 함수를 호출하면 명령이 존재하면 파괴되는 하위 쉘이 생성되므로 쉘에서 디렉토리를 변경하면 파이썬의 환경에 영향을 미치지 않습니다.

또한 하위 셸을 만드는 데 시간이 오래 걸리므로 OS 명령을 직접 사용하면 성능에 영향을줍니다

편집하다

몇 가지 타이밍 테스트를 실행했습니다.

In [379]: %timeit os.chmod('Documents/recipes.txt', 0755)
10000 loops, best of 3: 215 us per loop

In [380]: %timeit os.system('chmod 0755 Documents/recipes.txt')
100 loops, best of 3: 2.47 ms per loop

In [382]: %timeit call(['chmod', '0755', 'Documents/recipes.txt'])
100 loops, best of 3: 2.93 ms per loop

내부 기능이 10 배 이상 빠르게 실행

편집 2

외부 실행 파일을 호출하면 Python 패키지보다 더 나은 결과를 얻을 수있는 경우가 있습니다. 하위 프로세스를 통해 호출 된 gzip 의 성능이 자신이 사용한 Python 패키지의 성능보다 훨씬 높다는 내 동료가 보낸 메일을 기억했습니다 . 그러나 표준 OS 명령을 에뮬레이트하는 표준 OS 패키지에 대해 이야기 할 때는 확실히 아닙니다


답변

쉘 호출은 OS마다 다르지만 대부분의 경우 Python os 모듈 기능은 그렇지 않습니다. 그리고 하위 프로세스를 생성하지 않습니다.


답변

훨씬 더 효율적입니다. “쉘”은 많은 시스템 호출을 포함하는 또 다른 OS 바이너리입니다. 단일 시스템 호출에 대해서만 전체 쉘 프로세스를 작성하는 오버 헤드가 발생하는 이유는 무엇입니까?

os.system쉘 내장이 아닌 무언가를 사용할 때 상황은 더욱 악화됩니다 . 쉘 프로세스를 시작하여 실행 파일을 시작한 다음 (두 프로세스가 떨어져) 시스템을 호출합니다. 최소한 subprocess쉘 중개 프로세스의 필요성을 제거했을 것입니다.

이것은 파이썬에만 국한된 것이 아닙니다. systemd같은 이유로 Linux 시작 시간이 이렇게 개선되었습니다. 이는 수천 개의 쉘을 생성하는 대신 필요한 시스템 호출 자체를 만듭니다.


답변