Python3: Verschachtelte Funktionen in compile/exec Script



  • Hi!

    In einem bestehenden Programm können eigene Python3 Scripts eingebunden werden um eigene Funktionalität nachzurüsten. Diese Scriptdateien werden mit compile und exec verarbeitet. (Das Programm ist fix, es geht jetzt nur um die Scriptdatei.)

    Folgender Code (im Script) erzeugt einen Fehler:

    def a():
    	print("a")
    
    def b():
    	a()
    
    b()
    

    => NameError: name 'a' is not defined

    Vielleicht gibt es ja einen Python-Guru, der mir erklären kann was ich im Script machen muss, damit ich eigene Funktionen im Script auch in anderen Funktionen aufrufen kann? (Hängt mit Sicherheit mit globals/locals namespace zusammen...)

    Danke!



  • also bei mir geht's (python 3.4.5)


  • Mod

    zufallswert schrieb:

    also bei mir geht's (python 3.4.5)

    Dass dies korrektes Python ist, steht wohl außer Frage. Der TE möchte wissen, wieso er mit irgendeiner selbstaufgerufenen Python-API keinen Erfolg hat. Bloß fehlt leider jeder Kontext in der Fragestellung, daher ist es so gut wie nicht zu beantworten.



  • Das lässt sich auf folgendes Stück reduzieren:

    def test():
    	with open("script.py") as f:
    		cmpl = compile(f.read(), "script.py", "exec")
    		exec(cmpl)
    
    test()
    


  • Keiner eine Idee? 😕

    Etwas hässlich geht es, wenn ich in der Script-Datei nur ein import mache, dann kann ich in der importierten Datei selbst definierte Funktionen auch in anderen Funktionen aufrufen.

    main.py:

    def test():
        with open("script.py") as f:
            cmpl = compile(f.read(), "script.py", "exec")
            exec(cmpl)
    
    test()
    

    script.py:

    import scriptreal
    

    scriptreal.py:

    def a():
        print("a")
    
    def b():
        a()
    
    b()
    

    Mit __name__ Magic kann man das mit Sicherheit auch in einer Datei realisieren, aber hässlich bleibt es trotzdem. 🙄


  • Mod

    Es funktioniert wie gewünscht, wenn du dem exec noch einen Scope (locals() oder globals() gehen beide) mit übergibst. Aber erwarte keine Erklärung von mir, ich habe das bloß gegoogelt. Das ist, wie du selber schon vermutet hast, irgend so ein Problem mit Python Namespaces, bei dem ich wahrscheinlich Kopfschmerzen bekäme, würde ich genauer darüber nachdenken.



  • Okay, interessant.
    Leider ist das Hauptprogramm fix.


Log in to reply