os.system () 호출을 피하는 방법?
os.system ()을 사용할 때 파일 이름과 명령에 매개 변수로 전달 된 다른 인수를 이스케이프해야하는 경우가 종종 있습니다. 어떻게해야합니까? 여러 운영 체제 / 쉘에서 작동하지만 특히 bash에서는 작동하는 것이 좋습니다.
나는 현재 다음을하고 있지만, 이것에 대한 라이브러리 기능이나 적어도 더 우아하고 견고하고 효율적인 옵션이 있어야합니다.
def sh_escape(s):
return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
os.system("cat %s | grep something | sort > %s"
% (sh_escape(in_filename),
sh_escape(out_filename)))
편집 : 나는 따옴표를 사용하는 간단한 대답을 받아 들였습니다. 왜 그런 생각을하지 않았는지 모르겠습니다. '와'가 약간 다르게 동작하는 Windows에서 왔기 때문에 추측합니다.
보안과 관련하여 우려 사항을 이해하지만이 경우 os.system ()이 제공하는 빠르고 쉬운 솔루션에 관심이 있으며 문자열의 소스가 사용자가 생성하지 않았거나 적어도 신뢰할 수있는 사용자 (me).
이것이 내가 사용하는 것입니다 :
def shellquote(s):
return "'" + s.replace("'", "'\\''") + "'"
쉘은 항상 인용 된 파일 이름을 허용하고 주변의 인용 부호를 제거하여 해당 프로그램으로 전달합니다. 특히 공백이나 다른 종류의 불쾌한 셸 메타 문자가 포함 된 파일 이름의 문제를 피할 수 있습니다.
업데이트 : Python 3.3 이상을 사용하는 경우 직접 롤링하는 대신 shlex.quote 를 사용 하십시오.
shlex.quote()
파이썬 3부터 원하는 것을 수행합니다.
( pipes.quote
파이썬 2와 파이썬 3을 모두 지원하는 데 사용 )
아마도을 사용하는 특별한 이유가있을 것 os.system()
입니다. 그러나 그렇지 않다면 아마도 subprocess
모듈 을 사용해야 할 것입니다 . 파이프를 직접 지정하고 쉘 사용을 피할 수 있습니다.
Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0]
아마도 subprocess.list2cmdline
더 좋은 기회일까요?
pipes.quote는 실제로 Python 2.5 및 Python 3.1에서 손상되어 사용하기에 안전하지 않습니다. 길이가 0 인 인수는 처리하지 않습니다.
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
파이썬 이슈 7476 참조 ; 파이썬 2.6 및 3.2 이상에서 수정되었습니다.
os.system은 사용자를 위해 구성된 모든 명령 셸을 호출한다고 생각하므로 플랫폼 독립적 인 방식으로 수행 할 수 있다고 생각하지 않습니다. 내 명령 셸은 bash, emacs, ruby 또는 quake3의 것이 될 수 있습니다. 이 프로그램들 중 일부는 당신이 그들에게 전달하는 종류의 논쟁을 기대하지 않으며, 그들이 그렇게했다고 보장하지는 않더라도 그들은 같은 방식으로 탈출한다는 것을 보장하지 않습니다.
참고 : 이것은 Python 2.7.x에 대한 답변입니다.
에 따르면 소스 , pipes.quote()
"할 수있는 방법이다 안정적에 대해 하나의 인수로 문자열 인용 / 빈 / SH는 ". ( 버전 2.7 이후 로 더 이상 사용되지 않으며 마침내 Python 3.3에서 shlex.quote()
함수 로 공개적으로 노출되었습니다 .)
에 다른 한편으로 , subprocess.list2cmdline()
"할 수있는 방법 은 AS와 동일한 규칙을 사용하여 명령 행 문자열로 인수의 순서를 번역 MS C 런타임 ".
여기 명령 줄에 문자열을 인용하는 플랫폼 독립적 인 방법이 있습니다.
import sys
mswindows = (sys.platform == "win32")
if mswindows:
from subprocess import list2cmdline
quote_args = list2cmdline
else:
# POSIX
from pipes import quote
def quote_args(seq):
return ' '.join(quote(arg) for arg in seq)
용법:
# Quote a single argument
print quote_args(['my argument'])
# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)
내가 사용하는 기능은 다음과 같습니다
def quote_argument(argument):
return '"%s"' % (
argument
.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('$', '\\$')
.replace('`', '\\`')
)
즉, 항상 인수를 큰 따옴표로 묶은 다음 큰 따옴표 안에 특수 문자만을 역 슬래시 인용하십시오.
시스템 명령을 사용하면 os.system () 호출에 들어가는 것을 화이트리스트에 추가하려고 시도합니다. 예를 들어 ..
clean_user_input re.sub("[^a-zA-Z]", "", user_input)
os.system("ls %s" % (clean_user_input))
하위 프로세스 모듈이 더 나은 옵션이므로 가능한 한 os.system / subprocess와 같은 것을 사용하지 않는 것이 좋습니다.
실제 답은 : os.system()
처음부터 사용하지 마십시오 . subprocess.call
대신 사용 하고 이스케이프되지 않은 인수를 제공하십시오.
참고URL : https://stackoverflow.com/questions/35817/how-to-escape-os-system-calls
'developer tip' 카테고리의 다른 글
우편 번호 정규식 (0) | 2020.07.26 |
---|---|
Xcode 중복 라인 (0) | 2020.07.26 |
VIM + Syntastic : 검사기를 비활성화하는 방법? (0) | 2020.07.26 |
"이 작업을 수행하려면 Ruby 및 Sass를 설치하고 PATH에 설치해야합니다"경고를 해결하는 방법 경고? (0) | 2020.07.26 |
Jackson-일반 클래스를 사용하여 직렬화 해제 (0) | 2020.07.26 |