Programing

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

crosscheck 2020. 6. 5. 18:56
반응형

쉘 명령을 직접 실행하는 대신 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의 더 구체적인 메소드를 선호하는 네 가지 강력한 사례가 있습니다 .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달성 할 때 의도하지 않은 작업을 수행 할 수 있습니다.

Injection Safety (see shell injection examples):

If you use input from the user as a new command you've basically given him a shell. This is much like SQL injection providing a shell in the DB for the user.

An example would be a command of the form:

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

This can be easily exploited to run any arbitrary code using the input: NASTY COMMAND;# to create the eventual:

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

There are many such commands that can put your system at risk.


For a simple reason - when you call a shell function, it creates a sub-shell which is destroyed after your command exists, so if you change directory in a shell - it does not affect your environment in Python.

Besides, creating sub-shell is time consuming, so using OS commands directly will impact your performance

EDIT

I had some timing tests running:

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

Internal function runs more than 10 time faster

EDIT2

There may be cases when invoking external executable may yield better results than Python packages - I just remembered a mail sent by a colleague of mine that performance of gzip called through subprocess was much higher than the performance of a Python package he used. But certainly not when we are talking about standard OS packages emulating standard OS commands


Shell call are OS specific whereas Python os module functions are not, in most of the case. And it avoid spawning a subprocess.


It's far more efficient. The "shell" is just another OS binary which contains a lot of system calls. Why incur the overhead of creating the whole shell process just for that single system call?

The situation is even worse when you use os.system for something that's not a shell built-in. You start a shell process which in turn starts an executable which then (two processes away) makes the system call. At least subprocess would have removed the need for a shell intermediary process.

It's not specific to Python, this. systemd is such an improvement to Linux startup times for the same reason: it makes the necessary system calls itself instead of spawning a thousand shells.

참고URL : https://stackoverflow.com/questions/28572833/why-use-pythons-os-module-methods-instead-of-executing-shell-commands-directly

반응형