Come scarico (ricaricare) un modulo?


797

Ho un server Python di lunga durata e vorrei essere in grado di aggiornare un servizio senza riavviare il server. Qual è il modo migliore per farlo?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()

53
Suggerimento: "import" non significa "caricamento", significa "caricamento se non ancora caricato e quindi importazione nello spazio dei nomi".
Kos,

3
la domanda non dovrebbe includere "scarico" in quanto ciò non è ancora possibile in Python - ricaricare è tuttavia un paradigma noto come risposta di seguito
robertmoggach

Ho avuto lo stesso problema durante l'utilizzo di un modulo dinamico nell'app py2exe. Poiché py2exe mantiene sempre il bytecode nella directory zip, il ricaricamento non funzionava. Ma ho trovato una soluzione funzionante usando il modulo import_file. Ora la mia applicazione funziona bene.
Pritam Pan

2
Cosa succede se si desidera "scaricare" perché il codice tenta di eliminare un file .pyc?
darkgaze,

Risposte:


793

Puoi ricaricare un modulo quando è già stato importato usando la reloadfunzione integrata (solo Python 3.4+) :

from importlib import reload  
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

In Python 3, è reloadstato spostato nel impmodulo. In 3.4, è impstato deprecato a favore importlibe è reloadstato aggiunto a quest'ultimo. Quando scegli come target 3 o versioni successive, fai riferimento al modulo appropriato quando lo chiami reloado lo importi.

Penso che questo sia quello che vuoi. I server Web come il server di sviluppo di Django lo usano in modo da poter vedere gli effetti delle modifiche al codice senza riavviare il processo del server stesso.

Per citare dai documenti:

Il codice dei moduli Python viene ricompilato e il codice a livello di modulo viene rieseguito, definendo un nuovo set di oggetti che sono associati ai nomi nel dizionario del modulo. La funzione init dei moduli di estensione non viene chiamata una seconda volta. Come con tutti gli altri oggetti in Python, i vecchi oggetti vengono recuperati solo dopo che i loro conteggi di riferimento scendono a zero. I nomi nello spazio dei nomi del modulo vengono aggiornati per puntare a qualsiasi oggetto nuovo o modificato. Altri riferimenti ai vecchi oggetti (come nomi esterni al modulo) non vengono rimbalzati per fare riferimento ai nuovi oggetti e devono essere aggiornati in ogni spazio dei nomi in cui si verificano se lo si desidera.

Come hai notato nella tua domanda, dovrai ricostruire gli Foooggetti se la Fooclasse risiede nel foomodulo.


10
in realtà, il server dev django si riavvia quando si modifica un file .. (riavvia il server, non solo ricarica il modulo)
hasen

25
da dove viene questa funzione "is_changed"? non vedo documentazione su di esso e non funziona nel mio ambiente Python 3.1.3, né funziona in 2.6.4.
jedmao,

5
niente cdleary, Django non può semplicemente usare reload: pyunit.sourceforge.net/notes/reloading.html
raylu

14
@BartoszKP se Xnon è un modulo, puoiimport sys; reload(sys.modules[X.__module__])
drevicko

5
@jedmao @JamesDraper Sono abbastanza sicuro che la is_changedfunzione sia solo una funzione arbitraria che dovresti scrivere; non è un built-in. Ad esempio, potrebbe eventualmente aprire il file corrispondente al modulo che si sta importando e diffonderlo con una versione cache per vedere se è cambiato.
James Mchugh,

252

In Python 3.0–3.3 useresti: imp.reload(module)

Il BDFL ha risposto a questa domanda.

Tuttavia, è impstato deprecato in 3.4, a favore diimportlib (grazie @Stefan! ).

Io credo , quindi, che ci si ora possibile utilizzare importlib.reload(module), anche se non sono sicuro.


23
Il neofita sincero è grato di conoscere le sfumature critiche tra Python 2 e 3.
Smandoli,

24
imp.reload (imp) è valido?
Loïc Faure-Lacroix,

2
@ LoïcFaure-Lacroix reload(__builtins__)è valido allo stesso modo in 2.x
JBernardo,

1
@Tarrasch: è il modulo Python che vuoi ricaricare, come nell'esempio nella domanda.
Paul D. Waite,

3
@ LoïcFaure-Lacroix sì, l'Imp può ricaricarsi.
Devyn Collier Johnson,

92

Può essere particolarmente difficile eliminare un modulo se non è Python puro.

Ecco alcune informazioni da: Come posso davvero cancellare un modulo importato?

È possibile utilizzare sys.getrefcount () per scoprire il numero effettivo di riferimenti.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

I numeri maggiori di 3 indicano che sarà difficile liberarsi del modulo. Il modulo "vuoto" (non contenente nulla) nostrano dovrebbe essere raccolto dopo

>>> del sys.modules["empty"]
>>> del empty

come terzo riferimento è un artefatto della funzione getrefcount ().


4
Ho appena scoperto che se il modulo fa parte di un pacchetto, è necessario eliminarlo anche lì:setattr(package, "empty", None)
u0b34a0f6ae

6
Questa è la soluzione corretta, soprattutto se si dispone di un pacchetto con moduli nidificati. reload()ricarica solo il modulo più in alto e qualsiasi cosa al suo interno non verrà ricaricata a meno che non lo si elimini per la prima volta da sys.modules.
Cerin,

73

reload(module), ma solo se è completamente autonomo. Se qualcos'altro ha un riferimento al modulo (o qualsiasi oggetto appartenente al modulo), otterrai errori sottili e curiosi causati dal vecchio codice in giro più a lungo del previsto e cose come isinstancenon funzionare su diverse versioni del stesso codice.

Se si dispone di dipendenze a senso unico, è inoltre necessario ricaricare tutti i moduli che dipendono dal modulo ricaricato per eliminare tutti i riferimenti al vecchio codice. E quindi ricaricare i moduli che dipendono dai moduli ricaricati, in modo ricorsivo.

Se si hanno dipendenze circolari, cosa molto comune, ad esempio quando si ha a che fare con il ricaricamento di un pacchetto, è necessario scaricare tutti i moduli del gruppo in una volta sola. Non puoi farlo reload()perché reimporterà ogni modulo prima che le sue dipendenze siano state aggiornate, consentendo ai vecchi riferimenti di insinuarsi in nuovi moduli.

L'unico modo per farlo in questo caso è l'hacking sys.modules, che è un po 'non supportato. Dovresti passare attraverso ed eliminare ogni sys.modulesvoce che desideri ricaricare alla successiva importazione, nonché eliminare le voci i cui valori hanno Nonea che fare con un problema di implementazione relativo alla memorizzazione nella cache delle importazioni relative non riuscite. Non è terribilmente bello ma fintanto che hai un set completamente autonomo di dipendenze che non lascia riferimenti al di fuori della sua base di codice, è fattibile.

Probabilmente è meglio riavviare il server. :-)


1
Il dreload non è specifico per quello scenario?
Josh,

@Josh: no, serve per ricaricare un albero dei pacchetti, e anche allora funziona solo fino a quando il pacchetto non ha dipendenze esterne / circolari.
bobince

1
Riesci a elaborare la parte con i Nonevalori perché sto affrontando esattamente questo problema: sto eliminando gli elementi da sys.modulese dopo la reimportazione di alcune dipendenze importate None.
schlamar,

@shclamar: See stackoverflow.com/questions/1958417/... (ei collegamenti da lì) per lo sfondo. Non mi è chiaro (anche guardando il codice import.c) come le Nonevoci sono riuscite a tornare indietro attraverso il meccanismo di importazione quando le voci "reali" sono state eliminate, e non riesco a farlo accadere su 2.7; in futuro sicuramente non sarà più un problema poiché le importazioni relative implicite sono andate via. Nel frattempo, l'eliminazione di tutte le voci con Nonevalore sembra risolverlo.
mercoledì

1
@Eliethesaiyan: intendi la reloadfunzione? È integrato, non è necessario importare alcuna libreria.
bobince

63
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]

3
+1. Il mio obiettivo era quello di eseguire test del naso in Python. Dopo aver caricato un modulo e rinominato alcune funzioni, i vecchi nomi rimanevano quando si chiamava nose.run(), anche doporeload(my_module) %run my_module
Peter D

5
Se il modulo importa i propri sottomoduli, potrebbe essere necessario eliminare anche quelli. Qualcosa del genere [del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')].
drevicko,

Non penso che scarichi il modulo. Su Python 3.8: import sys; import json; del sys.modules['json']; print(json.dumps([1]))e il modulo json funziona ancora anche se non è più nei sys.modules.
Seperman,

60

Per Python 2 usa la funzione integrata reload () :

reload(module)

Per Python 2 e 3.2–3.3 usare ricaricare dal modulo imp :

import imp
imp.reload(module)

Ma imp è deprecato dalla versione 3.4 a favore di importlib , quindi usa:

import importlib
importlib.reload(module)

o

from importlib import reload
reload(module)

2
per gestire uno di questi casi: from six import reload_module(è necessario pip install sixprima ovviamente)
Anentropic

@Anentropic: si consiglia di utilizzare sei pacchetti, ma la sintassi è from six.moves import reload_module( doc )
x0s

23

Il seguente codice consente la compatibilità con Python 2/3:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

Puoi usarlo come reload()in entrambe le versioni, il che semplifica le cose.


18

La risposta accettata non gestisce il caso X importato da Y. Questo codice gestisce anche il caso di importazione standard:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

Nel caso del ricaricamento, riassegniamo i nomi di livello superiore ai valori memorizzati nel modulo appena ricaricato, che li aggiorna.


Notato un problema, globals () si riferisce al modulo in cui definisci questa funzione, quindi se lo definisci in un modulo diverso da quello in cui lo chiami non funziona.
Joseph Garvin,

Per interattivo, dopo >>> from X import Yricaricare fare>>> __import__('X', fromlist='Y')
Bob Stein

@ BobStein-VisiBone, c'è un modo per farlo funzionare quando fromlist='*'?
Mike C,

Bella domanda, non so @MikeC. A proposito, tendo a cessare quasi tutto l'uso fromnelle dichiarazioni di importazione. Semplicemente import <package>esplicito package.symbol nel codice. Renditi conto che questo potrebbe non essere sempre possibile o desiderabile. (Ecco un'eccezione: dal futuro import print_function.)
Bob Stein,

Mike C: quello che funziona per me èfoo = reload(foo); from foo import *
rampion

16

Questo è il modo moderno di ricaricare un modulo:

from importlib import reload

Se vuoi supportare versioni di Python precedenti alla 3.5, prova questo:

from sys import version_info
if version_info[0] < 3:
    pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
    from imp import reload # Python 3.0 - 3.4 
else:
    from importlib import reload # Python 3.5+

Per usarlo, esegui reload(MODULE), sostituendolo MODULEcon il modulo che vuoi ricaricare.

Ad esempio, reload(math)ricaricherà il mathmodulo.


4
O semplicemente from importlib import reload. Quindi puoi farlo reload(MODULE_NAME). Non è necessario per questa funzione.
pault

Credo che modulereload(MODULE_NAME)sia più autoesplicativo della semplice reload(MODULE_NAME)e abbia meno possibilità di entrare in conflitto con altre funzioni.
Richie Bendall,

@RichieBendall Siamo spiacenti, ma questa risposta è completamente sbagliata. La funzione reload () accetta l'oggetto modulo, non il nome del modulo ... Leggi la documentazione: docs.python.org/3/library/importlib.html#importlib.reload E sono d'accordo con @ pault - questo "come modulereload" è superfluo .
mbdevpl,

Ho cambiato la mia risposta per riflettere la tua opinione.
Richie Bendall,

13

Se si è non è in un server, ma in via di sviluppo e la necessità di frequenti ricaricare un modulo, ecco una bella mancia.

Innanzitutto, assicurati di utilizzare l'eccellente shell IPython , dal progetto Jupyter Notebook. Dopo aver installato Jupyter, puoi avviarlo con ipython, o jupyter console, o meglio jupyter qtconsole, che ti darà una bella console colorata con completamento del codice in qualsiasi sistema operativo.

Ora nella tua shell, digita:

%load_ext autoreload
%autoreload 2

Ora, ogni volta che esegui il tuo script, i tuoi moduli verranno ricaricati.

Oltre a 2, ci sono altre opzioni della magia di caricamento automatico :

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.

7

Per quelli come me che vogliono scaricare tutti i moduli (quando si esegue nell'interprete Python sotto Emacs ):

   for mod in sys.modules.values():
      reload(mod)

Ulteriori informazioni sono disponibili in Ricaricamento dei moduli Python .


In realtà questo non sembra funzionare in modo affidabile (in 2.6) perché non tutto sys.modules.values()è un modulo. Ad esempio: >>> type (sys.modules.values ​​() [1]) <class 'email.LazyImporter'> Quindi, se provo a eseguire quel codice, cade (so che non è inteso come una soluzione pratica, solo sottolineandolo).
Francis Davey,

Non funziona nemmeno nei precedenti pitoni - come scritto. Ho dovuto escludere alcuni nomi. Aggiornerò il post quando sposterò quel codice sul mio nuovo computer.

2
Funziona bene in Python 2.7 dopo alcune modifiche:if mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak,

2
Questo funziona bene per me: import imp [reload (m) for m in sys.modules.values ​​() se m e non " " in m .__ name e non imp.is_builtin (m .__ name__)]
Patrick Wolf

5

Enthought Traits ha un modulo che funziona abbastanza bene per questo. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Ricaricherà qualsiasi modulo che è stato modificato e aggiornerà altri moduli e oggetti istanziati che lo utilizzano. Non funziona il più delle volte con__very_private__ metodi e può soffocare sull'ereditarietà delle classi, ma mi fa risparmiare un sacco di tempo dal dover riavviare l'applicazione host quando si scrivono i guy PyQt o cose che girano all'interno di programmi come Maya o Nuke. Non funziona forse il 20-30% delle volte, ma è comunque incredibilmente utile.

Il pacchetto di Enthought non ricarica i file nel momento in cui cambiano - devi chiamarlo esplicitamente - ma non dovrebbe essere così difficile da implementare se ne hai davvero bisogno


5

Coloro che utilizzano python 3 e ricaricano da importlib.

Se hai problemi come sembra che il modulo non si ricarichi ... Questo perché ha bisogno di un po 'di tempo per ricompilare pyc (fino a 60 sec). Scrivo questo suggerimento solo per sapere se hai riscontrato questo tipo di problema.



3

Altra opzione Guarda che Python default importlib.reloadreimporterà semplicemente la libreria passata come argomento. Essa non ricaricare le librerie che il vostro lib importazione. Se hai modificato molti file e hai un pacchetto un po 'complesso da importare, devi eseguire un nuovo caricamento .

Se hai installato IPython o Jupyter , puoi usare una funzione per ricaricare in profondità tutte le librerie:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

Se non hai Jupyter, installalo con questo comando nella tua shell:

pip3 install jupyter

Sia questo dreload Ipython che reload () di importlib si lamentano reload() argument must be module. Sto usando un'importazione di funzione personalizzata e non sembra funzionare. L'uso dei moduli integrati funziona. :-( è una perdita di tempo ricaricare iPython per ogni piccola modifica che ho apportato al mio codice ...
m3nda

2

Modifica (risposta V2)

La soluzione di prima è buona solo per ottenere le informazioni di ripristino, ma non cambierà tutti i riferimenti (più di reloadma meno di quanto richiesto). Per impostare effettivamente anche tutti i riferimenti, ho dovuto andare nel Garbage Collector e riscrivere i riferimenti lì. Ora funziona perfettamente!

Si noti che ciò non funzionerà se il GC è spento o se si ricaricano dati non monitorati dal GC. Se non vuoi fare confusione con il GC, la risposta originale potrebbe essere sufficiente per te.

Nuovo codice:

import importlib
import inspect
import gc
from weakref import ref


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    # First, log all the references before reloading (because some references may be changed by the reload operation).
    module_tree = _get_tree_references_to_reset_recursively(module, module.__name__)

    new_module = importlib.reload(module)
    _reset_item_recursively(module, module_tree, new_module)


def _update_referrers(item, new_item):
    refs = gc.get_referrers(item)

    weak_ref_item = ref(item)
    for coll in refs:
        if type(coll) == dict:
            enumerator = coll.keys()
        elif type(coll) == list:
            enumerator = range(len(coll))
        else:
            continue

        for key in enumerator:

            if weak_ref_item() is None:
                # No refs are left in the GC
                return

            if coll[key] is weak_ref_item():
                coll[key] = new_item

def _get_tree_references_to_reset_recursively(item, module_name, grayed_out_item_ids = None):
    if grayed_out_item_ids is None:
        grayed_out_item_ids = set()

    item_tree = dict()
    attr_names = set(dir(item)) - _readonly_attrs
    for sub_item_name in attr_names:

        sub_item = getattr(item, sub_item_name)
        item_tree[sub_item_name] = [sub_item, None]

        try:
            # Will work for classes and functions defined in that module.
            mod_name = sub_item.__module__
        except AttributeError:
            mod_name = None

        # If this item was defined within this module, deep-reset
        if (mod_name is None) or (mod_name != module_name) or (id(sub_item) in grayed_out_item_ids) \
                or isinstance(sub_item, EnumMeta):
            continue

        grayed_out_item_ids.add(id(sub_item))
        item_tree[sub_item_name][1] = \
            _get_tree_references_to_reset_recursively(sub_item, module_name, grayed_out_item_ids)

    return item_tree


def _reset_item_recursively(item, item_subtree, new_item):

    # Set children first so we don't lose the current references.
    if item_subtree is not None:
        for sub_item_name, (sub_item, sub_item_tree) in item_subtree.items():

            try:
                new_sub_item = getattr(new_item, sub_item_name)
            except AttributeError:
                # The item doesn't exist in the reloaded module. Ignore.
                continue

            try:
                # Set the item
                _reset_item_recursively(sub_item, sub_item_tree, new_sub_item)
            except Exception as ex:
                pass

    _update_referrers(item, new_item)

Risposta originale

Come scritto nella risposta di @ bobince, se c'è già un riferimento a quel modulo in un altro modulo (specialmente se è stato importato con la asparola chiave like import numpy as np), quell'istanza non verrà sovrascritta.

Questo mi è sembrato abbastanza problematico quando ho applicato test che richiedevano uno stato di "clean-slate" dei moduli di configurazione, quindi ho scritto una funzione chiamata reset_moduleche usa importlibla reloadfunzione e sovrascrive ricorsivamente tutti gli attributi del modulo dichiarato. È stato testato con Python versione 3.6.

import importlib
import inspect
from enum import EnumMeta

_readonly_attrs = {'__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
               '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__get__',
               '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__',
               '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__',
               '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__',
               '__subclasshook__', '__weakref__', '__members__', '__mro__', '__itemsize__', '__isabstractmethod__',
               '__basicsize__', '__base__'}


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    new_module = importlib.reload(module)

    reset_items = set()

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    _reset_item_recursively(module, new_module, module.__name__, reset_items)


def _reset_item_recursively(item, new_item, module_name, reset_items=None):
    if reset_items is None:
        reset_items = set()

    attr_names = set(dir(item)) - _readonly_attrs

    for sitem_name in attr_names:

        sitem = getattr(item, sitem_name)
        new_sitem = getattr(new_item, sitem_name)

        try:
            # Set the item
            setattr(item, sitem_name, new_sitem)

            try:
                # Will work for classes and functions defined in that module.
                mod_name = sitem.__module__
            except AttributeError:
                mod_name = None

            # If this item was defined within this module, deep-reset
            if (mod_name is None) or (mod_name != module_name) or (id(sitem) in reset_items) \
                    or isinstance(sitem, EnumMeta):  # Deal with enums
                continue

            reset_items.add(id(sitem))
            _reset_item_recursively(sitem, new_sitem, module_name, reset_items)
        except Exception as ex:
            raise Exception(sitem_name) from ex

Nota: usare con cura! L'uso di questi su moduli non periferici (moduli che definiscono le classi utilizzate esternamente, ad esempio) potrebbe portare a problemi interni in Python (come problemi di decapaggio / non decapaggio).


1

per me nel caso di Abaqus è il modo in cui funziona. Immagina che il tuo file sia Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

Questa risposta è una copia diretta da qui: ebanshi.cc/questions/1942/…
SiHa,

0

Ho avuto molti problemi a provare a ricaricare qualcosa all'interno di Sublime Text, ma finalmente ho potuto scrivere questa utility per ricaricare i moduli su Sublime Text in base al codice sublime_plugin.py utilizzato per ricaricare i moduli.

Questo sotto ti accetta di ricaricare i moduli da percorsi con spazi sui loro nomi, quindi in seguito dopo il ricaricamento puoi semplicemente importare come fai di solito.

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

Se si esegue per la prima volta, questo dovrebbe caricare il modulo, ma se in seguito è possibile ripetere il metodo / funzione run_tests()ricaricherà i file di test. Con Sublime Text ( Python 3.3.6) questo accade molto perché il suo interprete non si chiude mai (a meno che non riavvii Sublime Text, cioè l' Python3.3interprete).


-1

Un altro modo potrebbe essere quello di importare il modulo in una funzione. In questo modo una volta completata la funzione, il modulo riceve la spazzatura raccolta.


4
Il modulo non riceverà mai la spazzatura raccolta perché almeno un riferimento globale è contenuto sys.modules.
Tutti i lavoratori sono essenziali il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.