2009-11-28 11 views
7

Ich habe einige Code, der eine Standard-Konfigurationsdatei lädt und ermöglicht dann die Benutzer ihre eigenen Python-Dateien als zusätzliche ergänzende Konfiguration oder überschreibt der Standardwerte liefern:Python: execfile aus dem Arbeitsverzeichnis der anderen Datei?

# foo.py 

def load(cfg_path=None): 
    # load default configuration 
    exec(default_config) 

    # load user-specific configuration 
    if cfg_path: 
     execfile(cfg_path) 

ist ein Problem gibt, aber: execfile() führt Richtlinien die von cfg_path angegebene Datei, als ob sie im Arbeitsverzeichnis von foo.py wäre, nicht in einem eigenen Arbeitsverzeichnis. Daher können import Direktiven möglicherweise fehlschlagen, wenn die cfg_path-Datei beispielsweise from m import x enthält, wobei m ein Modul im selben Verzeichnis wie cfg_path ist.

Wie kann ich execfile() aus dem Arbeitsverzeichnis des Arguments oder sonst ein äquivalentes Ergebnis erzielen? Außerdem wurde mir gesagt, dass execfile in Python 3 veraltet ist und dass ich exec verwenden sollte. Wenn es also einen besseren Weg gibt, dass ich das tun sollte, bin ich ganz Ohr.

Hinweis: Ich glaube nicht, dass Lösungen, die nur das Arbeitsverzeichnis ändern, korrekt sind. Das wird diese Module nicht auf den Modul-Suchpfad des Interpreters bringen, soweit ich das beurteilen kann.

Antwort

7

os.chdir können Sie das Arbeitsverzeichnis ändern, wie Sie möchten (Sie können das Arbeitsverzeichnis von cfg_path mit os.path.dirname extrahieren); Stellen Sie sicher, dass Sie zuerst das aktuelle Verzeichnis mit os.getcwd erhalten, wenn Sie es wiederherstellen möchten, wenn Sie die Ausführung von cfg_path beendet haben.

Python 3 ist in der Tat entfernen execfile (zugunsten einer Sequenz in dem Sie die Datei zu lesen, compile den Inhalt, dann exec sie), aber Sie brauchen keine Sorgen zu machen, wenn Sie sich gerade in Python Codierung sind 2.6, da Die 2to3 Source to Source-Übersetzung befasst sich mit all dem reibungslos und nahtlos.

Bearbeiten: das OP sagt in einem Kommentar, dass execfile einen separaten Prozess startet und das aktuelle Arbeitsverzeichnis nicht berücksichtigt. Das ist falsch, und hier ist ein Beispiel dafür, dass es ist:

import os 

def makeascript(where): 
    f = open(where, 'w') 
    f.write('import os\nprint "Dir in file:", os.getcwd()\n') 
    f.close() 

def main(): 
    where = '/tmp/bah.py' 
    makeascript(where) 
    execfile(where) 
    os.chdir('/tmp') 
    execfile(where) 

if __name__ == '__main__': 
    main() 

erzeugt dies auf meiner Maschine Laufausgang wie:

Dir in file: /Users/aleax/stko 
Dir in file: /private/tmp 

zeigt deutlich, dass execfiletut Halten Sie das Arbeitsverzeichnis verwenden, das ist wird zum Zeitpunkt execfile ausgeführt. (Wenn die ausgeführte Datei das Arbeitsverzeichnis ändert, wird das nach execfile zurückgegeben - genau, weil alles im gleichen Prozess stattfindet!).

Also, was auch immer Probleme die OP noch beobachtet wird nicht das aktuelle Arbeitsverzeichnis gebunden (es ist schwer zu diagnostizieren, was sie kann tatsächlich sein, ohne den Code und die genauen Details der beobachteten Probleme zu sehen ;-).

+0

Danke für Ihre Antwort. Leider scheint das bei mir nicht zu funktionieren. 'execfile()' scheint einen völlig neuen Prozess mit einem eigenen Arbeitsverzeichnis zu starten, das nicht dasselbe ist wie das, von dem ich starte. –

+0

Nein, @Kyle, 'execfile' startet keinen separaten Prozess und ** ** respektiert das aktuelle Arbeitsverzeichnis. Bearbeiten Sie meine Antwort, um ein einfaches Beispiel zu zeigen, dass Sie falsch liegen. –

Verwandte Themen