Python 3-직접 대체 된 것처럼 문자열을 실행하는 방법은 무엇입니까?

nj3

문제 설명

exec문자열이 exec직접 (적절한 들여 쓰기로) 대체 된 것처럼 함수 내에서 문자열 이 가능한지 궁금합니다 . 99.9 %의 경우에는 사용하지 말아야한다는 것을 이해하지만,해야할지 여부보다이 exec작업을 수행 할 수 있는지에 더 관심이 있습니다.

내가 원하는 동작은 다음과 같습니다.

GLOBAL_CONSTANT = 1

def test_func():
    def A():
        return GLOBAL_CONSTANT
    def B():
        return A()
    return B

func = test_func()
assert func() == 1

그러나 나는 대신 주어진다.

GLOBAL_CONSTANT = 1

EXEC_STR = """
def A():
    return GLOBAL_CONSTANT
def B():
    return A()
"""

def exec_and_extract(exec_str, var_name):
    # Insert code here

func = exec_and_extract(EXEC_STR, 'B')
assert func() == 1

실패한 시도

def exec_and_extract(exec_str, var_name):
    exec(EXEC_STR)  # equivalent to exec(EXEC_STR, globals(), locals())
    return locals()[var_name]

NameError: name 'A' is not defined호출 할 때 func()부터 A그리고 B내 존재 exec_and_extractlocals()실행하는 동안 만 실행 컨텍스트 A또는 B이다 exec_and_extractglobals().


def exec_and_extract(exec_str, var_name):
    exec(EXEC_STR, locals())  # equivalent to exec(EXEC_STR, locals(), locals())
    return locals()[var_name]

NameError: name 'GLOBAL_CONSTANT' is not defined호출 할 때 A내부에서 func()의 실행 컨텍스트 이후 Aexec_and_extractlocals()이 포함되어 있지 않습니다 GLOBAL_CONSTANT.


def exec_and_extract(exec_str, var_name):
    exec(EXEC_STR, globals())  # equivalent to exec(EXEC_STR, globals(), globals())
    return globals()[var_name]

작동하지만 동등하지 않은 전역 네임 스페이스를 오염시킵니다.


def exec_and_extract(exec_str, var_name):
    locals().update(globals())
    exec(EXEC_STR, locals())  # equivalent to exec(EXEC_STR, locals(), locals())
    return locals()[var_name]

작품 만의 전체 내용을 복사 할 필요가 exec_and_extractglobals()로의 locals()경우 시간 낭비 globals()대형 (이 인위적인 예에서는 적용되지 물론)입니다. 또한 인수 중 하나 exec_and_extractGLOBAL_CONSTANT(끔찍한 인수 이름) 인 경우 동작이 다르기 때문에 "코드에 붙여 넣기"버전과 미묘하게 동일하지 않습니다 ( "붙여 넣기"버전은 인수 값을 사용하는 반면 코드는 전역 상수 값을 사용합니다).

추가 제약

문제 설명의 "허점"을 덮으려고합니다.

  • exec_str값들은 글로벌 또는 로컬 변수 영역을 액세스 할 수있는 임의의 코드를 표현한다.
  • 솔루션 내에서 액세스되는 전역 범위 변수에 대한 분석이 필요하지 않아야합니다 exec_str.
  • exec_and_extract(글로벌 네임 스페이스 또는 기타)에 대한 후속 호출 사이에 "오염"이 없어야합니다 . 즉,이 예에서의 실행은 향후를 호출 할 때 참조 할 수 있도록 EXEC_STR남겨두면 안됩니다 .Aexec_and_extract
user2357112는 Monica를 지원합니다.

이것은 불가능 해. exec지역 변수 범위 역학과 나쁘게 상호 작용하며 이와 같은 것이 작동하기에는 너무 제한적입니다. 사실, 실행 된 문자열의 모든 로컬 변수 바인딩 작업exec 은 기본 로컬로 호출 하는 경우 일반 할당, 함수 정의, 클래스 정의, 가져 오기 등을 포함하여 정의되지 않은 동작 입니다. 문서 인용 :

기본 로컬은 아래의 locals () 함수에 대해 설명 된대로 작동합니다. 기본 로컬 사전에 대한 수정을 시도해서는 안됩니다. 함수 exec ()가 반환 된 후 지역에 대한 코드의 영향을 확인해야하는 경우 명시 적 지역 ​​사전을 전달합니다.

또한, 코드가 실행될 exec수없는 return, break, yield호출자 대신 다른 제어 흐름을 실행하거나. 그것은 할 수있는 break실행 된 코드의 일부, 또는이다 루프 return실행 된 코드에 정의 된 함수에서, 그러나 그것은 상호 작용 호출자의 제어 흐름과 함께 할 수 없습니다.


호출 함수의 로컬 (주석에서 언급했듯이)과 상호 작용할 수있는 요구 사항을 희생하고 호출자의 제어 흐름과 상호 작용하는 데 신경 쓰지 않는다면 코드의 AST를 새 함수 정의의 본문을 작성하고 다음을 실행합니다.

import ast
import sys

def exec_and_extract(code_string, var):
    original_ast = ast.parse(code_string)
    new_ast = ast.parse('def f(): return ' + var)
    fdef = new_ast.body[0]
    fdef.body = original_ast.body + fdef.body
    code_obj = compile(new_ast, '<string>', 'exec')

    gvars = sys._getframe(1).f_globals
    lvars = {}
    exec(code_obj, gvars, lvars)

    return lvars['f']()

실수로 입력에서 삼중 따옴표로 묶인 문자열에 추가 들여 쓰기를 삽입하는 것과 같은 문제를 방지하기 위해 문자열 형식 대신 AST 기반 접근 방식을 사용했습니다.

inspect호출자가 다른 모듈에 있더라도 자신의 전역이 exec_and_extract아닌을 호출 한 사람의 전역을 사용할 수 있습니다 exec_and_extract.

실행 된 코드에 정의 된 함수는 복사본이 아닌 실제 전역을 참조합니다.

수정 된 AST의 추가 래퍼 기능은 그렇지 않으면 발생할 수있는 일부 범위 문제를 방지합니다. 특히, 그렇지 않으면 예제 코드에서의 정의 B를 볼 수 없습니다 A.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Python 프로그램을 직접 실행하는 방법은 무엇입니까?

분류에서Dev

연결된 것처럼 보이도록 문자열 변수를 축소하는 방법은 무엇입니까?

분류에서Dev

Python 3 : 문자 범위에 대해 문자열을 분할하는 방법은 무엇입니까?

분류에서Dev

문자열에 대한 포인터를 함수에 보내는 것과 직접 문자열을 보내는 것의 차이점은 무엇입니까?

분류에서Dev

람다 실행을 직접 트리거 한 업로드 된 파일을 읽는 방법은 무엇입니까?

분류에서Dev

Python 3의 tkinter 파일 대화 상자에서 문자열을 얻는 방법은 무엇입니까?

분류에서Dev

VSCode의 대체에서 캡처 된 변수의 보간을 수행하는 방법은 무엇입니까?

분류에서Dev

노드 모듈을 직접 실행하는 방법은 무엇입니까?

분류에서Dev

연결된 목록에 대한 포인터를이 코드에서 연결된 목록 자체 인 것처럼 처리 할 수있는 방법은 무엇입니까?

분류에서Dev

Python을 통해 자바 스크립트에 포함 된 것처럼 보이는 블록 체인 데이터 웹 스크래핑, 이것이 올바른 접근 방식입니까?

분류에서Dev

Matlab은 무의미한 디렉토리에 설치된 것처럼 보입니다. 안전하게 실행 취소하는 방법은 무엇입니까?

분류에서Dev

매 시대마다지도 함수를 실행하는 대신 첫 번째 시대에서지도 함수로 생성 된 변환을 직접 사용하는 방법은 무엇입니까?

분류에서Dev

위임 된 선택자 및 직접 선택자에 대해 더 짧은 이벤트를 작성하는 방법은 무엇입니까?

분류에서Dev

기본 JQuery UI 자동 완성 대신 서버에서 직접 자동 완성을 실행하는 방법은 무엇입니까?

분류에서Dev

Windows에서 Python을 사용하여 EOF / Ctrl-Z 문자가 포함 된 대용량 텍스트 파일을 처리하는 방법은 무엇입니까?

분류에서Dev

하위 문자열에 임의의 문자가 대체 된 경우 하위 문자열을 찾는 방법은 무엇입니까?

분류에서Dev

bash의 명령 대체없이 출력 문자열을 실행하는 방법은 무엇입니까?

분류에서Dev

노틸러스에서 직접 실행 파일을 실행하는 방법은 무엇입니까?

분류에서Dev

스크롤 막대 화살표를 클릭하는 것처럼 실제 스크롤을 만드는 방법은 무엇입니까?

분류에서Dev

d3js에서 막대 문자에 수직선을 추가하는 방법은 무엇입니까?

분류에서Dev

전체 입력 문자열 (공백으로 구분 된 실수)이 Python의 정규식과 일치하는지 확인하는 방법은 무엇입니까?

분류에서Dev

R에서 누락 된 값을 평균으로 대체하여 처리하는 방법은 무엇입니까?

분류에서Dev

제공된 배포판 옆에 Python의 대체 버전을 설치하는 방법은 무엇입니까?

분류에서Dev

문자 코드가 포함 된 문자열을 처리하는 방법은 무엇입니까?

분류에서Dev

task.getException ()을 할 때 사용자가 이미 등록 된 것처럼 오류 메시지를 변경하는 방법은 무엇입니까?

분류에서Dev

OpenCV Python에서 전체 창에 대한 마우스 움직임을 캡처하는 방법은 무엇입니까?

분류에서Dev

사전에 대해 여러 캡처 된 문자열을 확인하고 누락 된 경우 경고하는 방법은 무엇입니까? (VBA)

분류에서Dev

Objective-C-Object가 마치 자신의 것처럼 IMP 메소드를 직접 실행할 수있는 방법이 있습니까?

분류에서Dev

htaccess를 사용하여 html 파일을 직접 보는 것을 방지하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    Python 프로그램을 직접 실행하는 방법은 무엇입니까?

  2. 2

    연결된 것처럼 보이도록 문자열 변수를 축소하는 방법은 무엇입니까?

  3. 3

    Python 3 : 문자 범위에 대해 문자열을 분할하는 방법은 무엇입니까?

  4. 4

    문자열에 대한 포인터를 함수에 보내는 것과 직접 문자열을 보내는 것의 차이점은 무엇입니까?

  5. 5

    람다 실행을 직접 트리거 한 업로드 된 파일을 읽는 방법은 무엇입니까?

  6. 6

    Python 3의 tkinter 파일 대화 상자에서 문자열을 얻는 방법은 무엇입니까?

  7. 7

    VSCode의 대체에서 캡처 된 변수의 보간을 수행하는 방법은 무엇입니까?

  8. 8

    노드 모듈을 직접 실행하는 방법은 무엇입니까?

  9. 9

    연결된 목록에 대한 포인터를이 코드에서 연결된 목록 자체 인 것처럼 처리 할 수있는 방법은 무엇입니까?

  10. 10

    Python을 통해 자바 스크립트에 포함 된 것처럼 보이는 블록 체인 데이터 웹 스크래핑, 이것이 올바른 접근 방식입니까?

  11. 11

    Matlab은 무의미한 디렉토리에 설치된 것처럼 보입니다. 안전하게 실행 취소하는 방법은 무엇입니까?

  12. 12

    매 시대마다지도 함수를 실행하는 대신 첫 번째 시대에서지도 함수로 생성 된 변환을 직접 사용하는 방법은 무엇입니까?

  13. 13

    위임 된 선택자 및 직접 선택자에 대해 더 짧은 이벤트를 작성하는 방법은 무엇입니까?

  14. 14

    기본 JQuery UI 자동 완성 대신 서버에서 직접 자동 완성을 실행하는 방법은 무엇입니까?

  15. 15

    Windows에서 Python을 사용하여 EOF / Ctrl-Z 문자가 포함 된 대용량 텍스트 파일을 처리하는 방법은 무엇입니까?

  16. 16

    하위 문자열에 임의의 문자가 대체 된 경우 하위 문자열을 찾는 방법은 무엇입니까?

  17. 17

    bash의 명령 대체없이 출력 문자열을 실행하는 방법은 무엇입니까?

  18. 18

    노틸러스에서 직접 실행 파일을 실행하는 방법은 무엇입니까?

  19. 19

    스크롤 막대 화살표를 클릭하는 것처럼 실제 스크롤을 만드는 방법은 무엇입니까?

  20. 20

    d3js에서 막대 문자에 수직선을 추가하는 방법은 무엇입니까?

  21. 21

    전체 입력 문자열 (공백으로 구분 된 실수)이 Python의 정규식과 일치하는지 확인하는 방법은 무엇입니까?

  22. 22

    R에서 누락 된 값을 평균으로 대체하여 처리하는 방법은 무엇입니까?

  23. 23

    제공된 배포판 옆에 Python의 대체 버전을 설치하는 방법은 무엇입니까?

  24. 24

    문자 코드가 포함 된 문자열을 처리하는 방법은 무엇입니까?

  25. 25

    task.getException ()을 할 때 사용자가 이미 등록 된 것처럼 오류 메시지를 변경하는 방법은 무엇입니까?

  26. 26

    OpenCV Python에서 전체 창에 대한 마우스 움직임을 캡처하는 방법은 무엇입니까?

  27. 27

    사전에 대해 여러 캡처 된 문자열을 확인하고 누락 된 경우 경고하는 방법은 무엇입니까? (VBA)

  28. 28

    Objective-C-Object가 마치 자신의 것처럼 IMP 메소드를 직접 실행할 수있는 방법이 있습니까?

  29. 29

    htaccess를 사용하여 html 파일을 직접 보는 것을 방지하는 방법은 무엇입니까?

뜨겁다태그

보관