557 Stimmen

Neuladen von Untermodule in IPython

Derzeit arbeite ich an einem Python-Projekt, das Untermodule enthält und numpy/scipy verwendet. Ipython wird als interaktive Konsole verwendet. Leider bin ich mit dem Workflow, den ich derzeit verwende, nicht sehr zufrieden, ich würde mich über einige Ratschläge freuen.

In IPython wird das Framework durch einen einfachen import-Befehl geladen. Es ist jedoch oft notwendig, Code in einem der Untermodule des Frameworks zu ändern. Zu diesem Zeitpunkt ist bereits ein Modell geladen und ich benutze IPython, um damit zu interagieren.

Das Framework enthält viele Module, die voneinander abhängen, d.h. wenn das Framework initial geladen wird, importiert und konfiguriert das Hauptmodul die Untermodule. Die Änderungen am Code werden nur ausgeführt, wenn das Modul unter Verwendung von reload(main_mod.sub_mod) neu geladen wird. Dies ist umständlich, da ich alle geänderten Module einzeln unter Verwendung des vollständigen Pfads neu laden muss. Es wäre sehr praktisch, wenn reload(main_module) auch alle Untermodule neu laden würde, jedoch ohne numpy/scipy neu zu laden.

0 Stimmen

Würden Sie sich gerne näher auf Allerdings ist es oft notwendig, den Code in einem der Untermodule des Frameworks zu ändern. näher erläutern? Warum ist es also notwendig, den Code zu ändern? Danke

32 Stimmen

@eat: Das Framework wird kontinuierlich weiterentwickelt, daher gibt es ständige Änderungen an der Code-Basis.

7voto

Pegasus Punkte 1248

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

Um das Tippen dieser magischen Funktionen zu vermeiden, können sie im IPython-Startskript platziert werden (Benennen Sie es mit der Erweiterung .py unter .ipython/profile_default/startup. Alle Python-Skripte in diesem Ordner werden gemäß der lexikalischen Reihenfolge geladen), das wie folgt aussieht:

from IPython import get_ipython
ipython = get_ipython()

ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")

0 Stimmen

Dies scheint auch zu funktionieren, wenn Sie Ihr Skript z.B. mit %run script.py aus der IPython-REPL ausführen.

5voto

Y.H Wong Punkte 6953

Wie wäre es damit:

import inspect

# muss mit einem leeren Set für geladen initialisiert werden
def recursively_reload_all_submodules(module, loaded=None):
    for name in dir(module):
        member = getattr(module, name)
        if inspect.ismodule(member) and member not in loaded:
            recursively_reload_all_submodules(member, loaded)
    loaded.add(module)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

Dies sollte effektiv den gesamten Baum der Module und Untermodule neu laden, die ihm gegeben werden. Sie können diese Funktion auch in Ihre .ipythonrc (glaube ich) setzen, damit sie jedes Mal geladen wird, wenn Sie den Interpreter starten.

0 Stimmen

Das sieht gut aus, jedoch könnte es sein, dass es nicht die Module oder Elemente von Modulen abdeckt, die mit from ... import ... oder import ... as importiert werden. Zumindest bereitet mir das oft Schwierigkeiten, wenn ich interaktiv auf der Konsole arbeite. Ich bin dazu übergegangen, gespeicherte Makros in IPython zu verwenden, die die erforderlichen Importe und Setups durchführen, um in einem vordefinierten Zustand zu arbeiten.

0 Stimmen

Es deckt tatsächlich from ... import ... und import ... as ab, solange das importierte Element ein Modul ist. Das einzige, was es nicht abdeckt, sind Module in einem Paket, die nicht aus seiner __init__.py-Datei geladen wurden. Für Pakete kannst du wahrscheinlich überprüfen, ob das __path__-Attribut des Moduls ein Verzeichnis ist. Wenn ja, durchsuche es und importiere rekursiv alle Module, die du finden konntest. Diesen Teil habe ich nicht geschrieben, weil der Autor nicht nach einer Lösung für Pakete gefragt hat.

0 Stimmen

Tatsächlich sieht das gut aus. Ich habe über diese Möglichkeit nachgedacht, aber gleichzeitig würde ich erwarten, dass es einige integrierte Funktionen gibt, d.h. basierend auf diesem. Allerdings war mir nicht klar, wie man das benutzt. Nach etwas Recherche, die vor meiner ursprünglichen Frage hätte stattfinden müssen, habe ich diese Erweiterung gefunden.

4voto

ryanjdillon Punkte 15461

Meine Standardpraxis zum Neuladen besteht darin, beide Methoden zu kombinieren, nachdem IPython zum ersten Mal geöffnet wurde:

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

Module laden, bevor dies durchgeführt wird, führt dazu, dass sie nicht neu geladen werden, selbst mit einem manuellen reload(module_name). Ich bekomme immer noch sehr selten unerklärliche Probleme mit Klassenmethoden, die nicht neu geladen werden und die ich noch nicht untersucht habe.

3voto

Leo Punkte 1560

Weitere Option:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

Überprüft auf ipython und ipython3 v5.1.0 auf Ubuntu 14.04.

3voto

user3897315 Punkte 480

Vor dem Importieren Ihrer Module fügen Sie diese Zeilen ein, wobei die erste überprüft, ob die Autoreload-Erweiterung bereits geladen wurde:

if 'autoreload' not in get_ipython().extension_manager.loaded:
    %load_ext autoreload
%autoreload 2

import sys
    .
    .
    .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X