Jak rozładować (przeładować) moduł Pythona?

Mam długo działający serwer Pythona i chciałbym móc uaktualnić usługę bez ponownego uruchamiania serwera. Jak najlepiej to zrobić?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
Author: Mark Harrison, 2009-01-13

19 answers

Możesz przeładować moduł, gdy został już zaimportowany za pomocą reload wbudowana funkcja w Pythonie 2:

import foo

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

W Pythonie 3, reload został przeniesiony do imp moduł. W 3.4, imp został wycofany na rzecz importlib, oraz reload dodano do tego ostatniego. Podczas targetowania 3 lub nowszego, odwołaj się do odpowiedniego modułu podczas wywołania reload lub zaimportuj go.

Myślę, że tego właśnie chcesz. Serwery WWW jak Django serwer programistyczny użyj tego, aby zobaczyć efekty zmian kodu bez ponownego uruchamiania samego procesu serwera.

Cytuję z docs:

Kod modułów Pythona jest rekompilowany i reexecuted kod poziomu modułu, definiowanie nowego zbioru obiektów, które są związane z nazwami w module słownik. Funkcja init moduły rozszerzeń nie są nazywane drugi raz. Podobnie jak w przypadku wszystkich innych obiektów w Pythonie stare obiekty są tylko odzyskane po liczbach referencji kropla do zera. Nazwy w module przestrzenie nazw są aktualizowane tak, aby wskazywały na dowolne nowe lub zmienione obiekty. Inne nawiązania do starych obiektów (takich jak nazwy zewnętrzne modułu) nie są rebound, aby odnosić się do nowych obiektów i muszą być aktualizowane w każdej przestrzeni nazw gdzie występują, jeśli jest to pożądane.

Jak zauważyłeś w swoim pytaniu, będziesz musiał zrekonstruować Foo obiekty, jeśli klasa Foo znajduje się w module foo.

 572
Author: cdleary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-25 15:37:25

W Pythonie 3.0–3.3 można by użyć: imp.reload(module)

BDFL ma odpowiedział na to pytanie.

Jednakże, imp został zdeprecjonowany w 3.4, na rzecz importlib (dzięki @Stefan!).

I myślę , dlatego teraz użyłbyś importlib.reload(module), chociaż nie jestem pewien.

 237
Author: Paul D. Waite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:30

Usunięcie modułu może być szczególnie trudne, jeśli nie jest to czysty Python.

Oto kilka informacji z: Jak naprawdę usunąć zaimportowany moduł?

Możesz użyć sys.getrefcount (), aby sprawdzić rzeczywistą liczbę referencje.

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

Liczby większe niż 3 wskazują, że trudno będzie się pozbyć moduł. Dom " pusty" (nie zawierającym nic) moduł powinien być garbage collected po

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

Jako że trzecie odniesienie jest artefaktem funkcji getrefcount ().

 75
Author: Gregg Lind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-13 22:41:43

reload(module), ale tylko wtedy, gdy jest całkowicie samodzielny. Jeśli cokolwiek innego ma odniesienie do modułu (lub dowolnego obiektu należącego do tego modułu), wtedy pojawią się subtelne i ciekawe błędy spowodowane tym, że stary kod będzie się kręcił dłużej niż oczekiwałeś, a rzeczy takie jak isinstance nie działają w różnych wersjach tego samego kodu.

Jeśli masz zależności jednokierunkowe, musisz również przeładować wszystkie moduły, które zależą od modułu reloaded, aby pozbyć się wszystkich odniesień do starego kodu. Oraz następnie przeładuj moduły, które zależą od przeładowanych modułów, rekurencyjnie.

Jeśli masz okrągłe zależności, co jest bardzo powszechne, na przykład, gdy masz do czynienia z przeładowaniem pakietu, musisz rozładować wszystkie moduły w grupie za jednym zamachem. Nie możesz tego zrobić z reload(), ponieważ zaimportuje on ponownie każdy moduł przed odświeżeniem jego zależności, pozwalając starym referencjom wkradać się do nowych modułów.

Jedynym sposobem na zrobienie tego w tym przypadku jest zhakowanie sys.modules, co jest rodzajem bez wsparcia. Aby poradzić sobie z problemem związanym z buforowaniem nie powiodło się importowanie względne, trzeba przejść przez i usunąć każdy wpis sys.modules, który chcesz przeładować przy następnym imporcie, a także usunąć wpisy, których wartości to None. Nie jest to zbyt miłe, ale dopóki masz w pełni samodzielny zestaw zależności, który nie pozostawia odniesień poza bazą kodową, jest to wykonalne.

Najlepiej zrestartować serwer. :-)

 59
Author: bobince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 06:15:43
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
 54
Author: Kumaresan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-04 06:36:45

W Pythonie 2 użyj wbudowanej funkcji reload():

reload(module)

Dla Pythona 2 i 3.2-3.3 użyj reload from module imp :

import imp
imp.reload(module)

Ale imp jest przestarzałe od wersji 3.4 na rzecz importlib , więc użyj:

import importlib
importlib.reload(module)

Lub

from importlib import reload
reload(module)
 35
Author: goetzc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 19:42:57

Poniższy kod pozwala na kompatybilność Pythona 2/3:

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

Można go używać jako reload() w obu wersjach, co ułatwia sprawę.

 20
Author: Matt Clarkson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-20 16:01:08

Zaakceptowana odpowiedź nie obsługuje przypadku from X import Y. Ten kod obsługuje go i Standardowy przypadek importu, jak również:

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")

W przypadku przeładowania, przypisujemy nazwy najwyższych poziomów do wartości przechowywanych w nowo załadowanym module, który je aktualizuje.

 14
Author: Joseph Garvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-28 02:26:31

Jest to nowoczesny sposób przeładowania modułu:

from importlib import reload

Po prostu wpisz reload(MODULE_NAME), zastępując MODULE_NAME nazwą modułu, który chcesz przeładować.

Na przykład, reload(math) przeładuje funkcję matematyczną.

 7
Author: Richie Bendall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-04 04:33:47

Dla takich jak ja, którzy chcą rozładować wszystkie moduły (podczas pracy w interpreterze Pythona pod Emacs):

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

Więcej informacji jest w przeładowywanie modułów Pythona.

 6
Author: Arkadiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 17:51:29

Jeśli jesteś nie na serwerze, ale rozwijasz i musisz często przeładowywać moduł, oto miła wskazówka.

Najpierw upewnij się, że używasz doskonałej powłoki IPython, z projektu Jupyter Notebook. Po zainstalowaniu Jupyter możesz uruchomić go z ipython lub jupyter console, lub jeszcze lepiej, jupyter qtconsole, co da ci ładną kolorową konsolę z uzupełnianiem kodu w dowolnym systemie operacyjnym.

Teraz w powłoce wpisz:

%load_ext autoreload
%autoreload 2

Teraz, za każdym razem uruchom skrypt, Twoje moduły zostaną przeładowane.

Poza 2, istnieją inne opcje magii autoreload :

%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.
 6
Author: neves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-08 17:56:46

Enthought Traits ma moduł, który działa dość dobrze do tego. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Spowoduje przeładowanie dowolnego modułu, który został zmieniony, oraz zaktualizuje inne moduły i Obiekty instancyjne, które go używają. Nie działa przez większość czasu z metodami __very_private__ i może się zadławić dziedziczeniem klas, ale oszczędza mi szaloną ilość czasu od konieczności ponownego uruchamiania aplikacji hosta podczas pisania GUI PyQt lub rzeczy, które działają wewnątrz programów takich jak Maya czy Nuke. To nie działa może 20-30% czasu, ale nadal jest niezwykle pomocne.

Pakiet Enthought nie ładuje ponownie plików w momencie ich zmiany - trzeba to jasno nazwać-ale nie powinno to być takie trudne do zaimplementowania, jeśli naprawdę tego potrzebujesz

 5
Author: flipthefrog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-09 01:06:14

2018-02-01

  1. moduł foo musi zostać zaimportowany z wyprzedzeniem.
  2. from importlib import reload, reload(foo)

31.5. importlib - implementacja dokumentacji import-Python 3.6.4

 2
Author: JawSaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 03:44:57

Ci, którzy używają Pythona 3 i przeładowują z importlib.

Jeśli masz problemy, jak się wydaje, że moduł nie przeładowuje się... To dlatego, że potrzebuje trochę czasu na rekompilację pyc(do 60 sek).Piszę tę podpowiedź tylko, że wiesz, czy doświadczyłeś tego rodzaju problemu.

 2
Author: PythonMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 11:00:43

Dla mnie w przypadku Abaqusa tak to działa. Wyobraź sobie, że Twój plik jest 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'])
 1
Author: Matt S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 14:27:12

Inna opcja. Zobacz, że Python default importlib.reload będzie po prostu ponownie zaimportować bibliotekę przekazaną jako argument. To nie spowoduje przeładowania bibliotek importowanych przez lib. Jeśli zmieniłeś wiele plików i masz nieco złożony pakiet do zaimportowania, musisz wykonać Głębokie przeładowanie .

Jeśli masz zainstalowany IPython lub Jupyter , możesz użyć funkcji do głębokiego przeładowania wszystkich bibliotek:

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

Jeśli nie masz Jupytera, zainstaluj go za pomocą tej komendy w swoim shell:

pip3 install jupyter
 1
Author: neves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-16 13:37:48

Miałem sporo problemów z przeładowaniem czegoś wewnątrz Sublime Text, ale w końcu mogłem napisać to narzędzie do przeładowania modułów na Sublime Text na podstawie kodu sublime_plugin.py używanego do przeładowania modułów.

To poniżej pozwala na przeładowanie modułów ze ścieżek ze spacjami na ich nazwach, a później po przeładowaniu możesz po prostu importować, jak zwykle.

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()

Jeśli uruchomisz się po raz pierwszy, powinno to załadować moduł, ale jeśli później możesz ponownie użyć metody / funkcji run_tests() przeładuj pliki testów. W przypadku Sublime Text (Python 3.3.6) zdarza się to często, ponieważ jego interpreter nigdy się nie zamyka (chyba że ponownie uruchomisz Sublime Text, np. interpreter Python3.3).

 0
Author: user,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 09:44:04

Innym sposobem może być zaimportowanie modułu do funkcji. W ten sposób po zakończeniu funkcji moduł pobiera śmieci.

 -1
Author: hackbot89,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-11 21:13:42

Operację unload można łatwo wykonać w następujący sposób:

import pythonlib
del pythonlib
Nie będziesz już miał nic związanego z tą biblioteką.
 -1
Author: Mincă Daniel Andrei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-16 13:12:01