나는 그런 파일 / 디렉토리를 생성하는 파일 속성을 변경하는 등 대신에 단지를 통해 해당 명령을 실행으로 OS 특정 작업을 실행하기위한 파이썬 라이브러리 함수를 사용하여 뒤에있는 동기 부여 무엇을 이해하려고 os.system()
하거나 subprocess.call()
?
예를 들어 왜하지 os.chmod
않고 사용 하고 os.system("chmod...")
싶습니까?
쉘 명령을 직접 실행하는 대신 가능한 파이썬의 라이브러리 메소드를 최대한 많이 사용하는 것이 “파이썬”이라는 것을 이해합니다. 그러나 기능적 관점에서이 작업을 수행하는 데 다른 동기가 있습니까?
여기서는 간단한 한 줄 쉘 명령 실행에 대해서만 이야기하고 있습니다. 우리는 작업 실행에 대한 더 많은 제어가 필요할 때 subprocess
예를 들어 모듈 을 사용 하는 것이 더 의미가 있음을 이해합니다 .
답변
-
그건 더 빨리 ,
os.system
그리고subprocess.call
일이 간단한에 대한 필요는 새로운 프로세스를 생성합니다. 사실,os.system
그리고subprocess.call
와shell
쉘되는 첫 번째, 그리고 (가 내장 같은 쉘이 아니라면 실행중인 것을 명령 인 두 번째 : 인수 일반적으로 두 개 이상의 새로운 프로세스를 생성test
). -
일부 명령은 별도의 프로세스에서 쓸모 가 없습니다 . 예를 들어을 실행
os.spawn("cd dir/")
하면 자식 프로세스의 현재 작업 디렉토리가 변경되지만 Python 프로세스는 변경되지 않습니다. 당신은 그것을 사용해야os.chdir
합니다. -
쉘이 해석 하는 특수 문자 에 대해 걱정할 필요가 없습니다 .
os.chmod(path, mode)
파일 이름이 무엇이든간에 작동하지만os.spawn("chmod 777 " + path)
파일 이름이과 같은 경우 끔찍하게 실패; rm -rf ~
합니다. 인수subprocess.call
없이 사용하면이 문제를 해결할 수 있습니다shell
. -
대시로 시작하는 파일 이름 에 대해 걱정할 필요가 없습니다 .
os.chmod("--quiet", mode)
는 파일 이름의 권한을 변경--quiet
하지만 인수로 해석되므로os.spawn("chmod 777 --quiet")
실패--quiet
합니다. 이것도 마찬가지입니다subprocess.call(["chmod", "777", "--quiet"])
. -
파이썬의 표준 라이브러리가 당신을 위해 처리해야하기 때문에 크로스 플랫폼 과 크로스 셸 문제 가 적습니다 . 시스템에
chmod
명령이 있습니까? 설치되어 있습니까? 지원할 것으로 예상되는 매개 변수를 지원합니까?os
이 불가능하다고 할 때 모듈은 가능한 크로스 플랫폼 및 문서로 일하려고합니다. -
실행중인 명령에 관심있는 출력 이있는 경우, 코너 케이스 (공백, 탭 및 줄 바꿈이있는 파일 이름)를 잊어 버릴 수 있으므로 소리보다 까다로워 야합니다. 이식성에 신경 쓰지 마십시오.
답변
더 안전합니다. 여기에 아이디어를 제공하는 예제 스크립트가 있습니다.
import os
file = raw_input("Please enter a file: ")
os.system("chmod 777 " + file)
사용자의 입력 인 경우 test; rm -rf ~
홈 디렉토리가 삭제됩니다.
이것이 내장 기능을 사용하는 것이 더 안전한 이유입니다.
따라서 시스템 대신 하위 프로세스를 사용해야하는 이유는 무엇입니까?
답변
명령을 실행할 때 또는 os
모듈을 사용 하는 것보다 모듈 에서 Python의보다 구체적인 메소드를 선호하는 경우가 4 가지 있습니다 .os.system
subprocess
- 중복성 -다른 프로세스를 생성하는 것은 중복되며 시간과 자원을 낭비합니다.
- 이식성 –
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 시작 시간이 이렇게 개선되었습니다. 이는 수천 개의 쉘을 생성하는 대신 필요한 시스템 호출 자체를 만듭니다.