C Python: Uruchamianie kodu Pythona w kontekście

Funkcja Python C APIPyEval_EvalCode uruchommy skompilowany kod Pythona. Chcę wykonać blok kodu Pythonatak jakby był wykonywany w ramach funkcji, dzięki czemu ma swój własny słownik zmiennych lokalnych, które nie wpływają na stan globalny.

Wydaje się to łatwe, ponieważPyEval_EvalCode pozwala dostarczyć słownik globalny i lokalny:

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

Problem, z którym się spotykam, dotyczy tego, jak Python wyszukuje nazwy zmiennych. Rozważmy następujący kod, który wykonujęPyEval_EvalCode:

myvar = 300
def func():
    return myvar

func()

Ten prosty kod powoduje błąd, ponieważ Python nie może znaleźć zmiennejmyvar z wewnątrzfunc. Nawet jeślimyvar jest w lokalnym słowniku w zewnętrznym zasięgu, Python nie kopiuje go do lokalnego słownika w wewnętrznym zakresie. Powód tego jest następujący:

Ilekroć Python szuka nazwy zmiennej, najpierw sprawdzalocals, to sprawdzaglobalsi wreszcie sprawdzabuiltins. Wzakres modułu, locals iglobals są obiektem słownika SAME. Więc oświadczeniex = 5 w zakresie modułu zostanie umieszczonyx w thelocals słownik, który jest równieżglobals słownik. Teraz funkcja zdefiniowana w zakresie modułu, który wymaga wyszukiwaniax nie znajdziex w zakresie funkcjilocals, ponieważ Python nie kopiuje lokali z zakresu modułów do lokali z zakresu funkcji. Ale to zwykle nie jest problem, ponieważ może go znaleźćx wglobals.

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

To tylko zzagnieżdżony funkcje, które Python wydaje się kopiować locals z zakresu zewnętrznego do locals zakresu wewnętrznego. (Wydaje się też, że robi to leniwie, tylko jeśli są potrzebne w wewnętrznym zakresie).

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


Rezultatem tego wszystkiego jest to, że podczas wykonywania kodu wzakres modułu, MUSISZ upewnić się, że słownik globalny i słownik lokalny są obiektem SAME, w przeciwnym razie funkcje zakresu modułu nie będą mogły uzyskać dostępu do zmiennych zakresu modułu.

Ale w moim przypadku nie chcę, aby słownik globalny i słownik lokalny były takie same. Potrzebuję więc sposobu, aby powiedzieć interpreterowi Pythona, że ​​wykonuję kod w zakresie funkcji. Czy jest jakiś sposób, aby to zrobić? Spojrzałem naPyCompileFlags jak również dodatkowe argumentyPyEval_EvalCodeEx i nie mogę znaleźć żadnego sposobu, aby to zrobić.

questionAnswers(1)

yourAnswerToTheQuestion