Bir modülü nasıl boşaltırım (yeniden yüklerim)?


797

Uzun süredir çalışan bir Python sunucum var ve sunucuyu yeniden başlatmadan bir hizmeti yükseltmek istiyorum. Bunu yapmanın en iyi yolu nedir?

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

53
Not ipucu: "içe aktar", "yükleme" anlamına gelmez, "henüz yüklenmediyse yükle ve ardından ad alanına aktar" anlamına gelir.
Kos

3
soru henüz '
python'da

Py2exe uygulamasında dinamik bir modül kullanırken aynı sorunu yaşadım. Py2exe her zaman zip dizin yeniden bayt kodu tutmak gibi çalışma değildi. Ancak import_file modülünü kullanarak çalışan bir çözüm buldum. Şimdi uygulamam iyi çalışıyor.
Pritam Pan

2
Kod tarafından bir .pyc dosyasını silmeye çalıştığınız için "kaldırmak" istiyorsanız ne olur?
darkgaze

Yanıtlar:


790

Yerleşikreload işlevi kullanarak önceden alınmışsa bir modülü yeniden yükleyebilirsiniz (yalnızca Python 3.4+) :

from importlib import reload  
import foo

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

Python 3'te, modüle reloadtaşındı imp. 3.4 yılında implehine kaldırıldı importlibve reloadikincisi eklendi. 3 veya daha üstünü hedeflerken, arama yaparken ilgili modüle başvurun reloadveya içe aktarın.

Bence istediğin bu. Django'nun geliştirme sunucusu gibi web sunucuları, sunucu işleminin kendisini yeniden başlatmadan kod değişikliklerinizin etkilerini görebilmeniz için bunu kullanır.

Dokümanlardan alıntı yapmak için:

Python modüllerinin kodu yeniden derlenir ve modül düzeyindeki kod yeniden verilir, böylece modül sözlüğündeki isimlere bağlı yeni bir nesne kümesi tanımlanır. Genişletme modüllerinin başlatma işlevi ikinci kez çağrılmaz. Python'daki diğer tüm nesnelerde olduğu gibi, eski nesneler yalnızca referans sayıları sıfıra düştükten sonra geri kazanılır. Modül ad alanındaki adlar yeni veya değiştirilmiş herhangi bir nesneyi işaret edecek şekilde güncellenir. Eski nesnelere (modüle harici adlar gibi) yapılan diğer başvurular, yeni nesnelere başvurmak için geri yüklenmez ve istenirse oluştukları her ad alanında güncellenmelidir.

Sorunuzda belirttiğiniz gibi Foo, Foosınıf foomodülde bulunuyorsa nesneleri yeniden yapılandırmanız gerekir .


10
Aslında, django dev sunucu yeniden başlatıldığında kendisi bir dosyayı değiştirdiğinizde .. (o sunucuyu yeniden başlatır, sadece modülü yeniden yükler)
Hasen

25
bu "is_changed" işlevi nereden geliyor? Ben hiçbir belge görmek ve benim Python 3.1.3 ortamında çalışmaz, ne de 2.6.4 çalışır.
jedmao

5
cdleary yok, Django sadece yeniden yükleme yapamaz
raylu

14
@BartoszKP Xbir modül değilse, şunları yapabilirsinizimport sys; reload(sys.modules[X.__module__])
drevicko

5
@jedmao @JamesDraper Bu is_changedfonksiyonun yazmak zorunda olacağınız keyfi bir fonksiyon olduğundan eminim ; yerleşik değildir. Örneğin, içe aktardığınız modüle karşılık gelen dosyayı açabilir ve değişip değişmediğini görmek için önbelleğe alınmış bir sürümle farklılaştırabilir.
James Mchugh

252

Python 3.0-3.3'te şunları kullanırsınız: imp.reload(module)

BDFL gelmiştir cevap bu soruyu.

Bununla birlikte, imp3.4 yılındaimportlib (teşekkürler @Stefan! ) Lehine önerilmemiştir .

Ben düşünüyorum bu nedenle, artık kullanıma ediyorum importlib.reload(module)emin değilim ancak.


23
En ciddi acemi, Python 2 ve 3 arasındaki kritik nüansları öğrenmek için minnettardır
Smandoli

24
.reload (imp) geçerli mi?
Loïc Faure-Lacroix

2
@ LoïcFaure-Lacroix aynı şekilde reload(__builtins__)2.x için geçerlidir
JBernardo

1
@Tarrasch: Yüklemek istediğiniz Python modülü, örneğin sorudaki gibi.
Paul D.Waite

3
@ LoïcFaure-Lacroix evet, imp kendini yeniden yükleyebilir.
Devyn Collier Johnson

92

Saf Python değilse bir modülü silmek özellikle zor olabilir.

Bazı bilgiler: İçe aktarılan bir modülü gerçekten nasıl silebilirim?

Gerçek referans sayısını bulmak için sys.getrefcount () kullanabilirsiniz.

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

3'ten büyük sayılar modülden kurtulmanın zor olacağını gösterir. Evde yetiştirilen "boş" (hiçbir şey içermeyen) modül,

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

üncü referans ise getrefcount () işlevinin bir ürünüdür.


4
Ben sadece modül bir paketin parçası ise, orada da silmek zorunda olduğunu setattr(package, "empty", None)
keşfettim

6
Bu, özellikle iç içe modüllere sahip bir paketiniz varsa, doğru çözümdür. reload()yalnızca en üstteki modülü yeniden yükler ve sys.modules'den silmediğiniz sürece içindeki hiçbir şey yeniden yüklenmez.
Cerin

73

reload(module)ancak yalnızca tamamen bağımsızsa. Modüle (veya modüle ait herhangi bir nesneye) başka bir şey referansı varsa, eski kodun beklediğinizden daha uzun süre asılı kalması ve isinstancefarklı sürümlerde çalışmama gibi şeyler gibi ince ve meraklı hatalar alırsınız . aynı kod.

Tek yönlü bağımlılıklarınız varsa, eski koda yapılan tüm başvurulardan kurtulmak için yeniden yüklenen modüle bağlı olan tüm modülleri de yeniden yüklemeniz gerekir. Ve sonra tekrar yüklenen modüllere bağlı olan modülleri tekrar tekrar yükleyin.

Örneğin, bir paketi yeniden yüklemekle uğraşırken çok yaygın olan dairesel bağımlılıklarınız varsa, gruptaki tüm modülleri tek seferde boşaltmanız gerekir. reload()Bağımlılıkları yenilenmeden önce her modülü yeniden içe aktaracak ve eski referansların yeni modüllere girmesine izin verecek şekilde bunu yapamazsınız .

Bu durumda bunu yapmanın tek yolu sys.modules, bir tür desteklenmeyen hack'lemektir. Bir sys.modulessonraki içe aktarma işleminde yeniden yüklenmesini istediğiniz her girdiyi incelemeniz ve silmeniz ve ayrıca, Nonebaşarısız göreli içe aktarmaların önbelleğe alınmasıyla ilgili bir uygulama sorunuyla ilgilenecek girdileri silmeniz gerekir . Çok güzel değil, ancak referansları kod tabanının dışında bırakmayan tamamen bağımsız bir bağımlılık kümeniz olduğu sürece, uygulanabilir.

Muhtemelen sunucuyu yeniden başlatmak en iyisidir. :-)


1
Dreload özellikle bu senaryo için değil mi?
Josh

@Josh: hayır, bir paket ağacını yeniden yüklemek içindir ve o zaman bile sadece paketin dış / dairesel bağımlılıkları olmadığı sürece çalışır.
bobince

1
NoneBu soruna tam olarak çalıştığım için değeri değerlere ayırabilir misiniz : sys.modulesBazı içe aktarılan bağımlılıklar yeniden içe aktarıldıktan sonra ve sonra öğeleri siliyorum None.
schlamar

@ shclamar: Arka plan için stackoverflow.com/questions/1958417/… (ve oradan gelen bağlantılar) bölümüne bakın . Benim için (hatta import.c koduna bakarak) Nonegirişler 'gerçek' girişler silindiğinde ithalat mekanizması üzerinden geri yol başardı nasıl belli değil, ve bunu 2.7 yapmak mümkün olamaz; gelecekte örtük göreceli ithalatlar ortadan kalktığından, bu kesinlikle bir sorun olmaktan çıkmıştır. Bu arada, tüm girişlerin Nonedeğerle silinmesi sorunu çözüyor gibi görünüyor.
Mart'ta bobince

1
@Eliethesaiyan: reloadişlevi mi demek istediniz ? Yerleşik, herhangi bir kitaplığı içe aktarmak zorunda değilsiniz.
bobince

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

3
+1. Amacım python içinde burun testleri yapmaktı. Bir modül yükledikten ve bazı fonksiyonları yeniden adlandırdıktan sonra, eski isimler arandıktan nose.run()sonra bile kaldıreload(my_module) %run my_module
Peter D

5
Modülünüz kendi alt modüllerini içeri aktarıyorsa, bunları da silmeniz gerekebilir. Gibi bir şey [del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')].
drevicko

Bunun modülün yüklemesini kaldırdığını sanmıyorum. Python 3.8'de: import sys; import json; del sys.modules['json']; print(json.dumps([1]))ve json modülü artık sys.modules'de olmasa bile hala çalışıyor.
Seperman

60

Python 2 için yerleşik yeniden işlev () işlevini kullanın :

reload(module)

Python 2 ve 3.2-3.3 için imp modülünden yeniden yükle'yi kullanın :

import imp
imp.reload(module)

Ancak importlib lehine sürüm 3.4'ten beri imp kullanımdan kaldırılmıştır , bu nedenle şunu kullanın:

import importlib
importlib.reload(module)

veya

from importlib import reload
reload(module)

2
Bu davalardan herhangi birini ele almak için: from six import reload_module( pip install sixönce elbette gerekir )
Anentropic

@Anentropic: Altı paket kullanmanızı öneririz, ancak sözdizimi from six.moves import reload_module( doc )
x0s

23

Aşağıdaki kod Python 2/3 uyumluluğuna izin verir:

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

Her reload()iki versiyonda olduğu gibi kullanabilirsiniz, bu da işleri kolaylaştırır.


18

Kabul edilen cevap, X içe aktarma Y durumuyla ilgilenmez. Bu kod, onu ve standart içe aktarma durumunu da ele alır:

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

Yeniden yükleme durumunda, en üst düzey adları yeniden yüklenen yeni yüklenen modülde depolanan değerlere yeniden atarız.


Bir sorun fark edildiğinde globals (), bu işlevi tanımladığınız modüle atıfta bulunur; bu nedenle, onu çağırdığınız modülden farklı bir modülde tanımlarsanız çalışmaz.
Joseph Garvin

Etkileşimli için, sonra >>> from X import Yyeniden yüklemek>>> __import__('X', fromlist='Y')
Bob Stein

@ BobStein-VisiBone, bunu ne zaman yapmanın bir yolu var fromlist='*'mı?
Mike C

Güzel soru, bilmiyorum @MikeC. Bu arada from, ithalat beyanlarında neredeyse tüm kullanımını durdurma eğilimindeyim . Kodda sade import <package>ve açık package.symbol. Bunun her zaman mümkün veya arzu edilmeyebileceğini anlayın. (İşte bir istisna: Gelecekteki ithalat print_function'dan.)
Bob Stein

Mike C: Benim için işe foo = reload(foo); from foo import *
yarayan

16

Bir modülü yeniden yüklemenin modern yolu:

from importlib import reload

3.5'ten eski Python sürümlerini desteklemek istiyorsanız, şunu deneyin:

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+

Kullanmak için, çalıştırın reload(MODULE), değiştirinMODULE yeniden yüklemek istediğiniz modül ile .

Örneğin reload(math), mathmodülü yeniden yükleyecektir.


4
Veya sadece yapın from importlib import reload. Sonra yapabilirsin reload(MODULE_NAME). Bu işleve gerek yoktur.
Şubat'ta

Sadece modulereload(MODULE_NAME)kendinden daha açıklayıcı olduğuna inanıyorum reload(MODULE_NAME)ve diğer işlevlerle çatışma şansı daha düşük.
Richie Bendall

@RichieBendall Üzgünüm, ama bu cevap tamamen yanlış. Reload () işlevi modül adını değil modül nesnesini alır ... docs.python.org/3/library/importlib.html#importlib.reload dosyasını kabul ediyorum ve @ pault ile aynı fikirdeyim - bu "modulereload olarak" gereksiz .
mbdevpl

Yanıtımı fikrinizi yansıtacak şekilde değiştirdim.
Richie Bendall

13

Eğer varsa değil bir sunucuda, ancak gelişmekte ve sık sık bir modül yeniden ihtiyaç Burada güzel bir ipucu.

İlk olarak, Jupyter Notebook projesinden mükemmel IPython kabuğunu kullandığınızdan emin olun . Jupyter yükledikten sonra, birlikte başlatabilirsiniz ipythonveya, jupyter consoleya da daha da iyisi,jupyter qtconsole size herhangi OS kod tamamlama ile güzel colorized konsolu verecek olan.

Şimdi kabuğunuza şunu yazın:

%load_ext autoreload
%autoreload 2

Şimdi, her seferinde komut dosyanızı çalıştırdığınızda, modülleriniz yeniden yüklenecektir.

Bunun ötesinde, otomatik yeniden yükleme sihrinin2 başka seçenekleri de vardır :

%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

Benim gibi tüm modülleri boşaltmak isteyenler için ( Emacs altındaki Python yorumlayıcısında çalışırken ):

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

Daha fazla bilgi Yeniden Yükleme Python modülleri .


Aslında bu güvenilir bir şekilde çalışmıyor gibi görünüyor (2.6'da) çünkü içindeki her şey sys.modules.values()bir modül değil. Örneğin: >>> type (sys.modules.values ​​() [1]) <class 'email.LazyImporter'> Yani bu kodu çalıştırmayı denersem devrilir (bunun pratik bir çözüm olmadığını düşünüyorum, sadece işaret ediyor).
Francis Davey

Yazıldığı gibi önceki pitonlarda bile çalışmaz. Bazı isimleri hariç tutmak zorunda kaldım. Bu kodu yeni bilgisayarıma taşıdığımda yazıyı güncelleyeceğim.

2
Bazı değişikliklerden sonra Python 2.7'de iyi çalışıyor:if mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak 15:12

2
Bu benim için iyi çalışıyor: m. Sod.modules.values ​​() içinde m için imp için yeniden yükleme (m) m .__ name içinde değil " " değil imp.is_builtin (m .__ name__)]
Patrick Wolf

5

Enthought Traits bunun için oldukça iyi çalışan bir modüle sahiptir. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Değiştirilen tüm modülleri yeniden yükler ve onu kullanan diğer modülleri ve örnek nesneleri günceller. Çoğu zaman __very_private__yöntemlerle çalışmaz ve sınıf mirasını boğabilir, ancak PyQt kılavuzu veya Maya veya Nuke gibi programların içinde çalışan şeyler yazarken ana bilgisayar uygulamasını yeniden başlatmak zorunda kalmamdan çılgınca zaman kazandırır. Belki% 20-30 oranında işe yaramaz, ancak yine de inanılmaz derecede yararlıdır.

Enthought'un paketi, değiştirildikleri anda dosyaları yeniden yüklemez - bunu açıkça çağırmanız gerekir - ancak gerçekten ihtiyacınız varsa uygulamak o kadar da zor olmamalıdır


5

Python 3 kullanan ve importlib'den yeniden yükleyenler.

Modül yeniden yüklenmiyor gibi görünüyorsa ... Pyc yeniden derlemek için biraz zamana ihtiyacı (60 saniyeye kadar) çünkü.



3

Diğer seçenek. Python varsayılanının importlib.reloadyalnızca argüman olarak geçirilen kütüphaneyi yeniden içe aktardığını görün. Bu olmaz sizin lib ithalat olduğunu kütüphaneleri yeniden yükleyin. Çok sayıda dosyayı değiştirdiyseniz ve içe aktarmak için biraz karmaşık bir paketiniz varsa, derin bir yeniden yükleme yapmanız gerekir .

Eğer varsa ipython veya Jupyter yüklü, derin yeniden yükleme tüm kütüphaneleri için bir işlevi kullanabilirsiniz:

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

Jupyter'iniz yoksa, kabuğunuzda bu komutla yükleyin:

pip3 install jupyter

Hem bu Ipython dreload hem de reload () importlib'den şikayet ediyor reload() argument must be module. Özel bir işlev içe aktarma kullanıyorum ve çalışmıyor gibi görünüyor. Yerleşik modülleri kullanmak işe yarar. :-(
Kodumda

2

Düzenle (Yanıt V2)

Önceden gelen çözüm, sadece sıfırlama bilgilerini almak için iyidir, ancak tüm referansları değiştirmez (gerektiğinden daha az reloadancak daha az). Aslında tüm referansları ayarlamak için, çöp toplayıcısına gitmem ve referansları yeniden yazmam gerekiyordu. Şimdi bir cazibe gibi çalışıyor!

GC kapalıysa veya GC tarafından izlenmeyen verileri yeniden yüklerseniz bunun işe yaramayacağını unutmayın . GC ile uğraşmak istemiyorsanız, orijinal cevap sizin için yeterli olabilir.

Yeni kod:

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)

Orijinal Yanıt

@ Bobince'nin cevabında yazıldığı gibi, başka bir modülde bu modüle zaten bir referans varsa (özellikle asbenzer anahtar kelimeyle içe aktarılmışsa import numpy as np), bu örneğin üzerine yazılmaz.

Yapılandırma modüllerinin "temiz kayrak" durumu gerektiren testleri uygularken bu benim için oldukça sorunlu oldu, bu yüzden 's işlevini reset_modulekullanan ve bildirilen tüm modül özniteliklerini tekrar tekrar üzerine yazan bir işlev yazdım . Python sürüm 3.6 ile test edilmiştir.importlibreload

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

Not: Dikkatli kullanın! Bunları çevresel olmayan modüllerde (örneğin harici olarak kullanılan sınıfları tanımlayan modüller) kullanmak Python'da dahili sorunlara neden olabilir (dekapaj / dekapaj sorunları).


1

Abaqus davası için benim için böyle çalışıyor. Dosyanızın Class_VerticesEdges.py olduğunu düşünün

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'])

Bu cevap buradan doğrudan bir kopyadır: ebanshi.cc/questions/1942/…
SiHa

0

Sublime Text içindeki bir şeyi yeniden yüklemeye çalışırken çok fazla sorunum var, ancak nihayet Sublime Text modüllerini yeniden yüklemek için kullanılan kodlara dayanarak modülleri yeniden yüklemek için bu yardımcı programı yazabilirim sublime_plugin.py.

Bu aşağıda, adları üzerinde boşluk bulunan yollardan modülleri yeniden yüklemenizi kabul eder, daha sonra yeniden yükledikten sonra genellikle yaptığınız gibi içe aktarabilirsiniz.

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

İlk kez çalıştırırsanız, bu modülü yüklemelidir, ancak daha sonra yöntemi / işlevi tekrar yapabiliyorsanız run_tests(), test dosyalarını yeniden yükleyecektir . Sublime Text ( Python 3.3.6) ile bu çok fazla olur çünkü tercümanı asla kapanmaz (Sublime Text'i yeniden başlatmazsanız, yani Python3.3tercüman).


-1

Başka bir yol, modülü bir işlevde içe aktarmak olabilir. Bu şekilde, modül tamamlandığında çöp toplanır.


4
Modül hiçbir zaman çöp toplamayacaktır çünkü en azından içeride küresel bir referans tutulur sys.modules.
Tüm İşçiler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.