programing

exec가 하위 기능이있는 함수에서 작동하지 않는 이유는 무엇입니까?

projobs 2021. 1. 19. 20:41
반응형

exec가 하위 기능이있는 함수에서 작동하지 않는 이유는 무엇입니까?


하위 기능이있는 함수에서 exec를 사용할 수없는 것 같습니다.

이 Python 코드가 작동하지 않는 이유를 아는 사람이 있습니까? test2의 exec에서 오류가 발생합니다. 또한 exec가 좋은 스타일이 아니라는 것을 알고 있지만 저를 믿으십시오. 적절한 이유로 exec를 사용하고 있습니다. 그렇지 않으면 사용하지 않을 것입니다.

#!/usr/bin/env python
#

def test1():
    exec('print "hi from test1"')

test1()

def test2():
    """Test with a subfunction."""
    exec('print "hi from test2"')
    def subfunction():
        return True

test2()

편집 : 하위 기능에 기능이 있도록 버그를 좁혔습니다. raise 키워드와는 관련이 없습니다.


옳은. 컨텍스트를 지정하지 않으면 하위 기능이있는 함수에서 exec를 사용할 수 없습니다. 문서에서 :

exec가 함수에서 사용되고 함수에 자유 변수가있는 중첩 블록이 포함되어있는 경우 exec가 exec에 대한 로컬 네임 스페이스를 명시 적으로 지정하지 않는 한 컴파일러는 SyntaxError를 발생시킵니다. (즉, "exec obj"는 불법이지만 "exec obj in ns"는 합법적입니다.)

일요일 밤이 아니었다면 아마 이해할만한 이유가 있습니다. 자, 다음 질문 : 왜 exec를 사용하고 있습니까? 거의 필요하지 않습니다. 당신은 정당한 이유가 있다고 말합니다. 나는 그것에 대해 회의적이다. ;) 타당한 이유가 있으면 해결 방법을 알려 드리겠습니다. :-피

오, 어쨌든 여기 있습니다.

def test2():
    """Test with a subfunction."""
    exec 'print "hi from test2"' in globals(), locals()
    def subfunction():
        return True

Python에서는 지역 변수가 사전에 저장되는 것처럼 보이지만 locals()일반적으로 그렇지 않습니다. 대신 대부분 스택에 저장되고 인덱스에 의해 액세스됩니다. 이렇게하면 매번 사전 조회를 수행해야하는 경우보다 로컬 변수 조회가 더 빨라집니다. locals()함수를 사용하면 모든 지역 변수에서 생성 된 새로운 사전이 생성되므로에 할당이 locals()일반적으로 작동하지 않습니다.

이 시나리오에는 몇 가지 예외가 있습니다.

exec함수 내에서 정규화되지 않은 것을 사용할 때 Python은 최적화를 끄고 로컬 변수에 실제 사전을 사용합니다. exec, 내부에서 변수를 만들거나 업데이트 할 수 있지만 해당 함수의 모든 로컬 변수 액세스가 더 느리게 실행된다는 의미이기도합니다.

다른 예외는 함수를 중첩 할 때 내부 함수가 외부 함수 범위의 지역 변수에 액세스 할 수 있다는 것입니다. 이렇게하면 변수가 스택에 저장되는 대신 '셀'개체에 저장됩니다. 추가 수준의 간접 지정으로 인해 내부 또는 외부 함수에서 액세스하든 범위 변수를 모두 더 느리게 사용할 수 있습니다.

당신이 만난 캐치는 지역 변수가 일반적으로 저장되는 방법에 대한 이러한 두 가지 예외가 호환되지 않는다는 것입니다. 변수를 사전에 저장하고 동시에 셀 참조를 통해 액세스 할 수 없습니다. Python 2.x는 범위 변수를 사용하지 않는 경우에도 exec를 허용하지 않음으로써이 문제를 해결합니다.


이것은 다소 흥미로운 경우입니다.

>>> def func():
...     exec('print "hi from func"')
...     def subfunction():
...         return True
... 
  File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'func' because 
it contains a nested function with free variables

이것이 실제로 작동하지 않는 이유 subfunction는 자유 변수 포함되어 있기 때문이며 Python 2에서는 exec이론적으로 포함 범위의 지역을 수정할 수 있기 때문에 변수가 전역 또는 부모에서 바인딩되어야하는지 여부를 결정할 수 없습니다. 기능 범위. Zen of Python의 구절 중 하나는 "모호함에 직면하여 추측하려는 유혹을 거부하십시오."입니다. 이것이 파이썬 2가하는 일입니다.

이제 질문은이 자유 (바인딩되지 않은) 변수가 무엇입니까? 글쎄요 True!

실제로 다음과 None같이 재현 가능합니다 .

>>> def func():
...     exec('print "hi from func"')
...     def subfunction():
...         return None
... 
  File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'test2' because it contains a nested
function with free variables

비록 None에 할당 할 수 없으며, 그것은으로 간주 일정 바이트 코드에서 버그 파서가 여기에 언 바운드 변수입니다 생각합니다.

그러나 그것을 대체하고 1문제없이 작동 한다면 :

>>> def test2():
...     exec('print "hi from func"')
...     def subfunction():
...         return 1
... 
>>>

이 오류를 방지하려면에서 사용할 전역 및 가능한 지역을 명시 적으로 지정하십시오 exec.

>>> def test2():
...     exec 'print "hi from test2"' in {}
...     def subfunction():
...         return None
...
>>>

Python 3에서는 exec단순한 함수일 뿐이며 파서 나 바이트 코드 컴파일러에 의해 특별히 처리되지 않습니다. Python 3에서는 exec함수 로컬 이름을 리 바인드 할 수 없으므로이 SyntaxError 및 모호성이 존재하지 않습니다.


Python 2 대 3 호환성의 특이한 경우는 Python 2.7 문서에 다음과 같이 명시되어 있다는 것입니다.

양식 exec(expr, globals)은과 동일 exec expr in globals하고 양식 exec(expr, globals, locals)은과 동일합니다 exec expr in globals, locals. 튜플 형식은 execPython 3과의 호환성 제공합니다. 여기서는 exec문이 아니라 함수입니다.

중첩 된 함수 exec있는 함수를 처리하는 데 버그 가 있었기 때문에 튜플 형식이 항상 100 % 호환되는 것은 아닙니다 (문제 21591) . Python 2.7.8까지 다음 코드에서 예외가 발생할 수 있습니다.

def func():
    exec('print "hi from test2"', {})
    def subfunction():
        return None

이것은 Python 2.7.9에서 수정되었으며 더 이상 던지지 않습니다.


print 함수를 사용하도록 print 문을 수정 한 후 Python 3.1.3에서 잘 작동합니다.

Python 2.6에서는을 생성 SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables하지만 버그라고 생각하지 않습니다.


오류는 나에게 상당히 명백한 것 같습니다.

SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables

자세한 정보는 pep 227을 참조하십시오 : http://www.python.org/dev/peps/pep-0227/


dictlist지능형 또한 파이썬 2.7.5에 하위 기능으로 간주 할 수있다

예를 들어 Python 2.7.5에서는 실패하지만 Python 2.7.12에서는 작동합니다.

def func():
    exec('print("a")')
    (str(e) for e in range(10))

와:

  File "./a.py", line 4
    exec('print("a")')
SyntaxError: unqualified exec is not allowed in function 'func' it contains a nested function with free variables

아마도 그것은 바이트 코드의 함수로 내부적으로 컴파일되었을 것입니다.

TODO find the fixing commit. It was beyond my git log --grep foo.

Analogous for dict comprehensions:

def func():
    exec('print("a")', {e:str(e) for e in range(10)})

which is specially bad since it is a common parameter for the global argument.

Also raised at: https://github.com/sphinx-doc/sphinx/issues/5417#issuecomment-421731085

ReferenceURL : https://stackoverflow.com/questions/4484872/why-doesnt-exec-work-in-a-function-with-a-subfunction

반응형