문자열에 포함된 Python 코드 실행
문제
저는 pygame과 box2d를 사용하여 게임 엔진을 작성하고 있으며 캐릭터 빌더에서 keydown 이벤트에서 실행될 코드를 작성할 수 있기를 원합니다.
내 계획은 캐릭터 빌더에 다음과 유사한 코드를 작성할 수 있는 텍스트 편집기를 두는 것이었습니다.
if key == K_a:
## Move left
pass
elif key == K_d:
## Move right
pass
텍스트 편집기의 내용을 문자열로 검색하고 이 Character 메서드의 메서드에서 코드를 실행하려고 합니다.
def keydown(self, key):
## Run code from text editor
그렇게 하는 가장 좋은 방법은 무엇입니까?
해결책
당신은 사용할 수 있습니다 eval(string)
이를 수행하는 방법.
정의
eval(code, globals=None, locals=None)
코드는 단지 표준 Python 코드입니다. 즉, 여전히 적절하게 들여쓰기가 필요합니다.
전역 변수는 사용자 정의를 가질 수 있습니다 __builtins__
보안 목적으로 유용할 수 있는 것으로 정의되었습니다.
예
eval("print('Hello')")
인쇄할 것 hello
콘솔에.코드에서 사용할 로컬 및 전역 변수를 지정할 수도 있습니다.
eval("print('Hello, %s'%name)", {}, {'name':'person-b'})
보안 문제
하지만 조심하세요.모든 사용자 입력이 실행됩니다.고려하다:
eval("import os;os.system('sudo rm -rf /')")
그 주위에는 여러 가지 방법이 있습니다.가장 쉬운 방법은 다음과 같이 하는 것입니다.
eval("import os;...", {'os':None})
하드 드라이브를 지우는 대신 예외가 발생합니다.귀하의 프로그램은 데스크톱이지만 사람들이 의도한 대로 스크립트를 재배포하는 경우 문제가 될 수 있습니다.
이상한 예
다음은 사용 예입니다. eval
오히려 이상하게도:
def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'
eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))
이것이 평가 라인에서 수행하는 작업은 다음과 같습니다.
- 현재 모듈에 다른 이름을 부여합니다.
contrivedExample
스크립트에).소비자가 전화할 수 있음contrivedExample.hello()
지금.) - 그것은 정의한다
hi
가리키는 것으로hello
- 해당 사전을 실행 모듈의 현재 전역 목록과 결합했습니다.
실패하다
실제로는 exec
성명.큰 죄송합니다.수정된 예시는 다음과 같습니다.
exec
정의
(이것은 친숙해 보인다!) exec는 진술입니다.
exec "code" [in scope]
범위는 지역 변수와 전역 변수의 사전입니다.지정하지 않으면 현재 범위에서 실행됩니다.
코드는 단지 표준 Python 코드입니다. 즉, 여전히 적절하게 들여쓰기가 필요합니다.
exec
예
exec "print('hello')"
인쇄할 것 hello
콘솔에.코드에서 사용할 로컬 및 전역 변수를 지정할 수도 있습니다.
eval "print('hello, '+name)" in {'name':'person-b'}
exec
보안 문제
하지만 조심하세요.모든 사용자 입력이 실행됩니다.고려하다:
exec "import os;os.system('sudo rm -rf /')"
명세서 인쇄
댓글 작성자도 지적했듯이, print
3.0 이전의 모든 Python 버전에 있는 명령문입니다.2.6에서는 다음을 입력하여 동작을 변경할 수 있습니다. from __future__ import print_statement
.그렇지 않으면 다음을 사용하십시오.
print "hello"
대신에 :
print("hello")
다른 팁
다른 사람들이 지적했듯이 텍스트를 문자열에로드하고 사용 할 수 있습니다. exec "codestring"
. 이미 파일에 포함 된 경우 사용합니다 execfile 로드하지 않아도됩니다.
한 가지 성능 참고 : Python 소스를 구문 분석하고 컴파일하는 것은 느린 프로세스이므로 코드를 여러 번 실행하지 않아야합니다. 즉. 가지고 있지 않음 :
def keydown(self, key):
exec user_code
소스를 코드 객체로 컴파일하여 이것을 조금 향상시킬 수 있습니다 ( compile()
그리고 당신이 주위에 유지하는 함수를 구성하고 한 번만 빌드하여 그것을 실행하십시오. 사용자가 "def my_handler (args ...)"를 작성하거나 직접 선발하고 다음과 같은 일을하도록 요구합니다.
user_source = "def user_func(args):\n" + '\n'.join(" "+line for line in user_source.splitlines())
d={}
exec user_source in d
user_func = d['user_func']
그런 다음 나중에 :
if key == K_a:
user_func(args)
당신이 사용할 수있는 eval()
평가 또는 실행. 프로그래밍 전에 Python 라이브러리 참조를 반드시 읽어야합니다.