Bagaimana cara menurunkan (memuat ulang) modul?

797

Saya memiliki server Python yang sudah berjalan lama dan ingin dapat meningkatkan layanan tanpa me-restart server. Apa cara terbaik melakukan ini?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
Mark Harrison
sumber
53
Kiat memo: "impor" tidak berarti "muat", itu berarti "muat jika belum dimuat, lalu impor ke ruang nama".
Kos
3
pertanyaannya seharusnya tidak termasuk 'membongkar' karena itu tidak mungkin dalam python - reload adalah paradigma yang dikenal seperti dijawab di bawah ini
robertmoggach
Saya memiliki masalah yang sama ketika menggunakan modul dinamis di aplikasi py2exe. Karena py2exe selalu menyimpan bytecode di direktori zip, reload tidak berfungsi. Tapi saya menemukan solusi yang berfungsi menggunakan modul import_file. Sekarang aplikasi saya berfungsi dengan baik.
Pritam Pan
2
Bagaimana jika Anda ingin "membongkar" karena mencoba menghapus file .pyc sedang digunakan oleh kode?
darkgaze

Jawaban:

793

Anda dapat memuat ulang modul ketika sudah diimpor dengan menggunakan reloadfungsi builtin (hanya Python 3.4+) :

from importlib import reload  
import foo

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

Dalam Python 3, reloaddipindahkan ke impmodul. Dalam 3.4, imptidak digunakan lagi importlib, dan reloadditambahkan ke yang terakhir. Saat menargetkan 3 atau lebih baru, rujuk modul yang sesuai saat memanggil reloadatau mengimpornya.

Saya pikir inilah yang Anda inginkan. Server web seperti server pengembangan Django menggunakan ini sehingga Anda dapat melihat efek dari perubahan kode Anda tanpa memulai ulang proses server itu sendiri.

Mengutip dari dokumen:

Kode modul python dikompilasi ulang dan kode level modul dieksekusi kembali, mendefinisikan seperangkat objek baru yang terikat pada nama-nama dalam kamus modul. Fungsi init dari modul ekstensi tidak disebut kedua kalinya. Seperti semua objek lain dalam Python, objek lama hanya direklamasi setelah jumlah referensi turun menjadi nol. Nama-nama dalam namespace modul diperbarui untuk menunjuk ke objek baru atau yang diubah. Referensi lain ke objek lama (seperti nama di luar modul) tidak kembali untuk merujuk ke objek baru dan harus diperbarui di setiap ruang nama tempat mereka muncul jika diinginkan.

Seperti yang Anda catat dalam pertanyaan Anda, Anda harus merekonstruksi Fooobjek jika Fookelas berada di foomodul.

cdleary
sumber
10
sebenarnya, Django dev Server restart sendiri ketika Anda mengubah file .. (restart server, bukan hanya reload modul)
Hasen
25
dari mana fungsi "is_changed" ini berasal? saya tidak melihat dokumentasi di dalamnya dan tidak berjalan di lingkungan Python 3.1.3 saya, juga tidak berjalan di 2.6.4.
jedmao
5
tanpa cdleary, Django tidak bisa hanya menggunakan isi ulang: pyunit.sourceforge.net/notes/reloading.html
raylu
14
@ BartoszKP jika Xbukan modul, Anda bisaimport sys; reload(sys.modules[X.__module__])
drevicko
5
@jedmao @JamesDraper Saya cukup yakin bahwa is_changedfungsi ini hanyalah fungsi arbitrer yang harus Anda tulis; ini bukan built-in. Sebagai contoh, itu bisa membuka file yang sesuai dengan modul yang Anda impor dan memperbaikinya dengan versi cache untuk melihat apakah itu berubah.
James Mchugh
252

Dalam Python 3.0–3.3 Anda akan menggunakan: imp.reload(module)

The BDFL telah menjawab pertanyaan ini.

Namun, impsudah usang dalam 3.4, mendukungimportlib (terima kasih @Stefan! ).

Saya pikir , oleh karena itu, sekarang Anda akan menggunakan importlib.reload(module), meskipun saya tidak yakin.

Paul D. Waite
sumber
23
Pemula yang
24
apakah imp.reload (imp) valid?
Loïc Faure-Lacroix
2
@ LoïcFaure-Lacroix dengan cara yang sama reload(__builtins__)berlaku di 2.x
JBernardo
1
@ Tarrasch: ini adalah modul Python yang ingin Anda muat ulang, seperti dalam contoh di pertanyaan.
Paul D. Waite
3
@ LoïcFaure-Lacroix ya, imp bisa memuat ulang sendiri.
Devyn Collier Johnson
92

Ini bisa sangat sulit untuk menghapus modul jika itu bukan Python murni.

Berikut ini beberapa informasi dari: Bagaimana cara saya benar-benar menghapus modul yang diimpor?

Anda dapat menggunakan sys.getrefcount () untuk mengetahui jumlah referensi aktual.

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

Angka yang lebih besar dari 3 menunjukkan bahwa akan sulit untuk menyingkirkan modul. Modul "kosong" (tidak mengandung apa-apa) buatan sendiri harus diambil setelahnya

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

sebagai referensi ketiga adalah artefak dari fungsi getrefcount ().

Gregg Lind
sumber
4
Saya baru saja menemukan bahwa jika modul tersebut merupakan bagian dari sebuah paket, Anda harus menghapusnya juga di sana:setattr(package, "empty", None)
u0b34a0f6ae
6
Ini adalah solusi yang tepat, terutama jika Anda memiliki paket dengan modul bersarang. reload()hanya memuat ulang modul paling atas, dan apa pun di dalamnya tidak akan dimuat ulang kecuali Anda terlebih dahulu menghapusnya dari sys.modules.
Cerin
73

reload(module), tetapi hanya jika itu sepenuhnya berdiri sendiri. Jika ada hal lain yang memiliki referensi ke modul (atau objek apa pun yang termasuk dalam modul), maka Anda akan mendapatkan kesalahan halus dan aneh yang disebabkan oleh kode lama yang berkeliaran lebih lama dari yang Anda harapkan, dan hal-hal seperti isinstancetidak bekerja di berbagai versi berbeda dari modul. kode yang sama.

Jika Anda memiliki dependensi satu arah, Anda juga harus memuat ulang semua modul yang bergantung pada modul yang dimuat ulang untuk menyingkirkan semua referensi ke kode lama. Dan kemudian memuat kembali modul yang bergantung pada modul yang dimuat ulang, secara rekursif.

Jika Anda memiliki dependensi melingkar, yang sangat umum misalnya ketika Anda berurusan dengan memuat ulang paket, Anda harus membongkar semua modul dalam grup sekaligus. Anda tidak dapat melakukan ini dengan reload()karena itu akan mengimpor kembali setiap modul sebelum dependensinya telah di-refresh, memungkinkan referensi lama masuk ke modul-modul baru.

Satu-satunya cara untuk melakukannya dalam hal ini adalah meretas sys.modules, yang agak tidak didukung. Anda harus melalui dan menghapus setiap sys.modulesentri yang ingin Anda muat ulang pada impor berikutnya, dan juga menghapus entri yang nilainya Noneberurusan dengan masalah implementasi terkait dengan caching impor relatif yang gagal. Ini tidak terlalu bagus tetapi selama Anda memiliki satu set dependensi mandiri yang tidak meninggalkan referensi di luar basis kode, itu bisa diterapkan.

Mungkin yang terbaik untuk me-restart server. :-)

bobince
sumber
1
Bukankah memuat secara khusus untuk skenario itu?
Josh
@Josh: tidak, ini untuk memuat ulang pohon paket, dan itupun hanya berfungsi selama paket tidak memiliki dependensi luar / bundar.
bobince
1
Bisakah Anda menguraikan bagian dengan Nonenilai - nilai karena saya menjalankan persis masalah ini: Saya menghapus item dari sys.modulesdan setelah mengimpor kembali beberapa dependensi yang diimpor None.
schlamar
@shclamar: Lihat stackoverflow.com/questions/1958417/… (dan tautan dari sana) untuk latar belakang. Tidak jelas bagi saya (bahkan melihat kode import.c) bagaimana Noneentri berhasil membuat jalan kembali melalui mekanisme impor ketika entri 'nyata' dihapus, dan saya tidak bisa mewujudkannya pada 2.7; di masa depan tentu itu tidak lagi menjadi masalah karena impor relatif implisit telah hilang. Sementara itu, menghapus semua entri dengan Nonenilai tampaknya memperbaikinya.
bobince
1
@Eliethesaiyan: maksud Anda reloadfungsinya? Ini built-in, Anda tidak perlu mengimpor perpustakaan apa pun.
bobince
63
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
Kumaresan
sumber
3
+1. Tujuan saya adalah menjalankan tes hidung dengan python. Setelah saya memuat modul dan berganti nama beberapa fungsi, nama-nama lama tetap ketika memanggil nose.run(), bahkan setelahreload(my_module) %run my_module
Peter D
5
Jika modul Anda mengimpornya sendiri, Anda mungkin perlu menghapusnya juga. Sesuatu seperti [del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')].
drevicko
Saya tidak berpikir itu menurunkan modul. Pada Python 3.8: import sys; import json; del sys.modules['json']; print(json.dumps([1]))dan modul json masih berfungsi meskipun tidak ada di sys.modules lagi.
Seperman
60

Untuk Python 2 gunakan fungsi reload bawaan () :

reload(module)

Untuk Python 2 dan 3.2-3.3 gunakan ulang dari modul imp :

import imp
imp.reload(module)

Tetapi imp sudah ditinggalkan sejak versi 3.4 yang mendukung importlib , jadi gunakan:

import importlib
importlib.reload(module)

atau

from importlib import reload
reload(module)
goetzc
sumber
2
untuk menangani salah satu dari kasus-kasus ini: from six import reload_module(harus pip install sixterlebih dahulu tentu saja)
Anentropic
@Anentropic: Ini saran yang bagus untuk merekomendasikan menggunakan enam paket, tetapi sintaksnya adalah from six.moves import reload_module( doc )
x0s
23

Kode berikut memungkinkan Anda kompatibilitas Python 2/3:

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

Anda dapat menggunakannya seperti reload()di kedua versi yang membuat semuanya lebih sederhana.

Matt Clarkson
sumber
18

Jawaban yang diterima tidak menangani kasus dari X import Y. Kode ini menanganinya dan kasing standar juga:

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

Dalam kasus memuat ulang, kami menetapkan kembali nama tingkat atas ke nilai yang disimpan dalam modul yang baru dimuat, yang memperbaruinya.

Joseph Garvin
sumber
Melihat masalah, globals () merujuk ke modul tempat Anda mendefinisikan fungsi ini, jadi jika Anda mendefinisikannya dalam modul yang berbeda dari yang Anda panggil dalam hal ini tidak berfungsi.
Joseph Garvin
Untuk interaktif, setelah >>> from X import Ymemuat ulang lakukan>>> __import__('X', fromlist='Y')
Bob Stein
@ BobStein-VisiBone, adakah cara untuk membuat itu bekerja kapan fromlist='*'?
Mike C
Pertanyaan bagus, tidak tahu @MikeC. Ngomong-ngomong, saya cenderung menghentikan hampir semua penggunaan fromdalam laporan impor. Hanya paket.simbol yang import <package>jelas dan eksplisit dalam kode. Sadarilah ini mungkin tidak selalu mungkin atau diinginkan. (Ini satu pengecualian: dari import print_function yang akan datang.)
Bob Stein
Mike C: apa yang berhasil bagi saya adalahfoo = reload(foo); from foo import *
rampion
16

Ini adalah cara modern memuat ulang modul:

from importlib import reload

Jika Anda ingin mendukung versi Python yang lebih lama dari 3,5, coba ini:

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+

Untuk menggunakannya, jalankan reload(MODULE), ganti MODULEdengan modul yang ingin Anda muat ulang.

Misalnya, reload(math)akan memuat ulang mathmodul.

Richie Bendall
sumber
4
Atau lakukan saja from importlib import reload. Maka Anda bisa melakukannya reload(MODULE_NAME). Tidak perlu untuk fungsi ini.
buka
Saya percaya modulereload(MODULE_NAME)lebih jelas dari pada adil reload(MODULE_NAME)dan memiliki peluang lebih rendah untuk konflik dengan fungsi lain.
Richie Bendall
@RichieBendall Maaf, tapi jawaban ini sepenuhnya salah. Fungsi reload () mengambil objek modul, bukan nama modul ... Baca dokumen: docs.python.org/3/library/importlib.html#importlib.reload Dan saya setuju dengan @ pault - ini "sebagai modulereload" superflous .
mbdevpl
Saya telah mengubah jawaban saya untuk mencerminkan pendapat Anda.
Richie Bendall
13

Jika Anda tidak berada di server, tetapi sedang mengembangkan dan perlu sering memuat ulang modul, inilah tip yang bagus.

Pertama, pastikan Anda menggunakan shell IPython yang luar biasa , dari proyek Notebook Jupyter. Setelah menginstal Jupyter, Anda dapat memulainya dengan ipython, atau jupyter console, atau bahkan lebih baik jupyter qtconsole,, yang akan memberi Anda konsol berwarna yang bagus dengan penyelesaian kode di OS apa pun.

Sekarang di shell Anda, ketik:

%load_ext autoreload
%autoreload 2

Sekarang, setiap kali Anda menjalankan skrip, modul Anda akan dimuat ulang.

Di luar itu 2, ada opsi lain dari autoreload magic :

%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.
neves
sumber
7

Bagi mereka seperti saya yang ingin membongkar semua modul (saat menjalankan interpreter Python di bawah Emacs ):

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

Informasi lebih lanjut ada di Reload modul Python .

Peter Mortensen
sumber
Sebenarnya itu tampaknya tidak berfungsi dengan baik (di 2.6) karena tidak semua yang sys.modules.values()ada dalam modul. Sebagai contoh: >>> ketik (sys.modules.values ​​() [1]) <class 'email.LazyImporter'> Jadi, jika saya mencoba menjalankan kode yang terjatuh (Saya Tahu itu tidak dimaksudkan sebagai solusi praktis, cukup menunjukkan itu).
Francis Davey
Ia bahkan tidak bekerja pada ular sanca sebelumnya - seperti yang tertulis. Saya harus mengecualikan beberapa nama. Saya akan memperbarui pos ketika saya memindahkan kode itu ke komputer baru saya.
2
Bekerja dengan baik di Python 2.7 setelah beberapa modifikasi:if mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak
2
Ini berfungsi dengan baik untuk saya: impor imp [reload (m) untuk m di sys.modules.values ​​() jika m dan bukan " " dalam nama m .__ dan bukan imp.is_builtin (m .__ name__)]
Patrick Wolf
5

Ciri-ciri Enthought memiliki modul yang bekerja cukup baik untuk ini. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Ini akan memuat kembali modul apa pun yang telah diubah, dan memperbarui modul lain dan objek yang digunakan yang menggunakannya. Itu tidak bekerja sebagian besar waktu dengan __very_private__metode, dan dapat tersedak warisan kelas, tapi itu menghemat waktu yang gila karena harus me-restart aplikasi host ketika menulis PyQt guis, atau hal-hal yang berjalan di dalam program seperti Maya atau Nuke. Itu tidak berhasil mungkin 20-30% dari waktu, tetapi masih sangat membantu.

Paket Enthought tidak memuat ulang file saat mereka berubah - Anda harus menyebutnya secara eksplisit - tetapi itu seharusnya tidak terlalu sulit untuk diterapkan jika Anda benar-benar membutuhkannya

flipthefrog
sumber
5

Mereka yang menggunakan python 3 dan memuat ulang dari importlib.

Jika Anda memiliki masalah seperti itu tampaknya modul tidak memuat ulang ... Itu karena perlu beberapa waktu untuk mengkompilasi ulang pyc (hingga 60 detik). Saya menulis petunjuk ini hanya agar Anda tahu jika Anda pernah mengalami masalah seperti ini.

PythonMan
sumber
3

Pilihan lain. Lihat bahwa standar Python importlib.reloadhanya akan mengimpor kembali pustaka yang diteruskan sebagai argumen. Itu tidak akan memuat ulang perpustakaan yang diimpor lib Anda. Jika Anda mengubah banyak file dan memiliki paket yang agak rumit untuk diimpor, Anda harus melakukan pemuatan ulang yang dalam .

Jika Anda menginstal IPython atau Jupyter , Anda dapat menggunakan fungsi untuk memuat ulang semua lib secara mendalam:

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

Jika Anda tidak memiliki Jupyter, instal dengan perintah ini di shell Anda:

pip3 install jupyter
neves
sumber
Baik dreload Ipython ini dan reload () dari importlib tidak mengeluh reload() argument must be module. Saya menggunakan impor fungsi khusus dan sepertinya tidak berfungsi. Menggunakan modul bawaan tidak berfungsi. :-( itu buang-buang waktu me-reload iPython untuk setiap perubahan kecil yang saya lakukan pada kode saya ...
m3nda
2

Edit (Jawab V2)

Solusi dari sebelumnya baik untuk hanya mendapatkan informasi reset, tetapi tidak akan mengubah semua referensi (lebih dari reloadtetapi kurang dari yang dibutuhkan). Untuk benar-benar mengatur semua referensi juga, saya harus pergi ke pengumpul sampah, dan menulis ulang referensi di sana. Sekarang ini berfungsi seperti pesona!

Perhatikan bahwa ini tidak akan berfungsi jika GC dimatikan, atau jika memuat ulang data yang tidak dipantau oleh GC. Jika Anda tidak ingin mengacaukan dengan GC, jawaban asli mungkin cukup untuk Anda.

Kode baru:

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)

Jawaban Asli

Seperti yang ditulis dalam jawaban @ bobince, jika sudah ada referensi ke modul itu di modul lain (terutama jika itu diimpor dengan askata kunci seperti import numpy as np), contoh itu tidak akan ditimpa.

Hal ini terbukti cukup bermasalah dengan saya ketika menerapkan tes yang diperlukan "bersih-batu tulis" keadaan modul konfigurasi, jadi saya telah menulis sebuah fungsi bernama reset_moduleyang menggunakan importlib's reloadfungsi dan secara rekursif menimpa semua atribut modul dideklarasikan ini. Telah diuji dengan Python versi 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

Catatan: Gunakan dengan hati-hati! Menggunakan ini pada modul non-periferal (modul yang mendefinisikan kelas yang digunakan secara eksternal, misalnya) dapat menyebabkan masalah internal dengan Python (seperti masalah pickling / un-pickling).

EZLearner
sumber
1

bagi saya untuk kasus Abaqus itu cara kerjanya. Bayangkan file Anda adalah 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'])
Matt S
sumber
Jawaban ini adalah salinan langsung dari sini: ebanshi.cc/questions/1942/…
SiHa
0

Saya mendapat banyak kesulitan mencoba memuat ulang sesuatu di dalam Sublime Text, tetapi akhirnya saya dapat menulis utilitas ini untuk memuat kembali modul pada Sublime Text berdasarkan kode yang sublime_plugin.pydigunakan untuk memuat kembali modul.

Di bawah ini menerima Anda untuk memuat ulang modul dari jalur dengan spasi di namanya, kemudian setelah memuat ulang Anda dapat mengimpor seperti biasa.

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

Jika Anda menjalankan untuk pertama kalinya, ini akan memuat modul, tetapi jika nanti Anda dapat kembali metode / fungsinya run_tests()itu akan memuat kembali file tes. Dengan Sublime Text ( Python 3.3.6) ini sering terjadi karena interpreternya tidak pernah ditutup (kecuali Anda me-restart Sublime Text, yaitu Python3.3interpreter).

pengguna
sumber
-1

Cara lain bisa dengan mengimpor modul dalam suatu fungsi. Dengan cara ini ketika fungsi selesai modul mendapat sampah yang dikumpulkan.

hackbot89
sumber
4
Modul tidak akan pernah mengumpulkan sampah karena referensi global diadakan setidaknya di sys.modules.
Semua Pekerja Sangat Penting