C Python: Executando o código Python dentro de um contexto

A função da API do Python CPyEval_EvalCode vamos executar código Python compilado. Eu quero executar um bloco de código Pythoncomo se estivesse executando dentro do escopo de uma função, de modo que ele tenha seu próprio dicionário de variáveis ​​locais que não afetam o estado global.

Isso parece fácil de fazer, já quePyEval_EvalCode permite fornecer um dicionário global e local:

PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)

O problema que eu corri tem a ver com a forma como o Python procura nomes de variáveis. Considere o seguinte código, que eu executo comPyEval_EvalCode:

myvar = 300
def func():
    return myvar

func()

Este código simples, na verdade, gera um erro, porque o Python é incapaz de encontrar a variávelmyvar de dentrofunc. Apesar demyvar está no dicionário local no escopo externo, o Python não o copia no dicionário local no escopo interno. A razão para isso é a seguinte:

Sempre que o Python procurar um nome de variável, primeiro ele verificalocals, então verificaglobalse finalmente verificabuiltins. Noescopo do módulo, locals eglobals são o mesmo objeto do dicionário. Então a afirmaçãox = 5 no escopo do módulo irá colocarx no olocals dicionário, que é também oglobals dicionário. Agora, uma função definida no escopo do módulo que precisa procurarx não vai encontrarx dentro do escopo da funçãolocals, porque o Python não copia locals de escopo de módulo em locais de escopo de função. Mas isso normalmente não é um problema, porque pode encontrarx emglobals.

x = 5
def foo():
   print(x) # This works because 'x' in globals() == True

É só comaninhado funções, que o Python parece copiar os locais do escopo externo em locais do escopo interno. (Também parece fazê-lo preguiçosamente, somente se forem necessários dentro do escopo interno).

def foo():
   x = 5
   def bar():
      print(x) # Now 'x' in locals() == True
   bar()


Então o resultado de tudo isso é que, ao executar o código emescopo do módulo, você precisa ter certeza de que seu dicionário global e dicionário local são o mesmo objeto, caso contrário, funções de escopo de módulo não poderão acessar variáveis ​​de escopo de módulo.

Mas no meu caso, eu não quero que o dicionário global e o dicionário local sejam os mesmos. Então eu preciso de alguma maneira de dizer ao interpretador Python que estou executando o código no escopo da função. Existe alguma maneira de fazer isso? Olhei para oPyCompileFlags bem como os argumentos adicionais paraPyEval_EvalCodeEx e não consigo encontrar nenhuma maneira de fazer isso.

questionAnswers(1)

yourAnswerToTheQuestion