मैं एक मॉड्यूल को कैसे पुनः लोड (पुनः लोड) करूं?


797

मेरे पास एक लंबे समय तक चलने वाला पायथन सर्वर है और मैं सर्वर को फिर से शुरू किए बिना किसी सेवा को अपग्रेड करने में सक्षम होना चाहूंगा। ऐसा करने का सबसे अच्छा तरीका क्या है?

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

53
मेमो टिप: "आयात" का अर्थ "लोड" नहीं है, इसका मतलब है "लोड अगर अभी तक लोड नहीं हुआ है और फिर नामस्थान में आयात करें"।
कोस

3
प्रश्न में 'अनलोड' को शामिल नहीं किया जाना चाहिए क्योंकि अभी तक अजगर में संभव नहीं है - फिर भी
उतारा

P22exe ऐप में डायनामिक मॉड्यूल का उपयोग करने पर मुझे यही समस्या थी। के रूप में py2exe हमेशा ज़िप निर्देशिका में बाइटकोड को फिर से लोड करता है काम नहीं कर रहा था। लेकिन मुझे import_file मॉड्यूल का उपयोग करके एक कार्यशील समाधान मिला। अब मेरा आवेदन ठीक काम कर रहा है।
प्रीतम पान

2
क्या होगा यदि आप "अनलोड" करना चाहते हैं क्योंकि एक .pyc फ़ाइल को हटाने की कोशिश कोड द्वारा की जा रही है?
अंधेरे में

जवाबों:


788

आप किसी मॉड्यूल को फिर से लोड कर सकते हैं जब यह reloadबिल्टिन फ़ंक्शन (केवल पायथॉन 3.4+ केवल) का उपयोग करके आयात किया गया है :

from importlib import reload  
import foo

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

पायथन 3 में, मॉड्यूल reloadमें ले जाया गया imp। 3.4 में, के impपक्ष में पदावनत किया गया था importlib, और reloadबाद में जोड़ा गया था। 3 या बाद में लक्षित करते समय, या तो कॉल करते समय reloadया आयात करते समय उपयुक्त मॉड्यूल को देखें ।

मुझे लगता है कि यह वही है जो आप चाहते हैं। Django के विकास सर्वर जैसे वेब सर्वर इसका उपयोग करते हैं ताकि आप सर्वर कोड को फिर से शुरू किए बिना अपने कोड परिवर्तनों के प्रभाव को देख सकें।

डॉक्स से उद्धृत करने के लिए:

पायथन मॉड्यूल के कोड को फिर से जोड़ दिया जाता है और मॉड्यूल-स्तरीय कोड को फिर से जोड़ा जाता है, जो वस्तुओं के एक नए सेट को परिभाषित करता है जो मॉड्यूल के शब्दकोश में नामों से बंधा होता है। विस्तार मॉड्यूल के init फ़ंक्शन को दूसरी बार नहीं कहा जाता है। पाइथन की अन्य सभी वस्तुओं की तरह ही पुरानी वस्तुओं को भी उनके संदर्भ के शून्य में गिराए जाने के बाद ही पुनः प्राप्त किया जाता है। मॉड्यूल नेमस्पेस में नाम किसी भी नई या परिवर्तित वस्तुओं को इंगित करने के लिए अपडेट किए जाते हैं। पुरानी वस्तुओं के अन्य संदर्भ (जैसे कि मॉड्यूल के बाहरी नाम) नई वस्तुओं को संदर्भित करने के लिए पलटाव नहीं करते हैं और प्रत्येक नामस्थान में अपडेट किया जाना चाहिए जहां वे वांछित हैं।

जैसा कि आपने अपने प्रश्न में उल्लेख किया है, यदि आप वर्ग मॉड्यूल में रहते हैं , तो आपको Fooवस्तुओं का पुनर्निर्माण करना होगा ।Foofoo


10
वास्तव में, django dev सर्वर तब ही पुनरारंभ होता है जब आप एक फ़ाइल बदलते हैं .. (यह सर्वर को पुनः आरंभ करता है, न कि केवल मॉड्यूल को पुनः लोड करता है)
hasen

25
यह "is_changed" फ़ंक्शन कहाँ से आ रहा है? मुझे इस पर कोई प्रलेखन नहीं दिखता है और यह मेरे पायथन 3.1.3 वातावरण में नहीं चलता है, न ही यह 2.6.4 में चलता है।
जेड्मो

5
कोई cdleary, Django बस पुनः लोड का उपयोग नहीं कर सकता: pyunit.sourceforge.net/notes/reloading.html
raylu

14
@BartoszKP Xएक मॉड्यूल नहीं है, तो आप कर सकते हैंimport sys; reload(sys.modules[X.__module__])
drevicko

5
@jedmao @JamesDraper मुझे पूरा यकीन है कि is_changedसमारोह सिर्फ एक मनमाना कार्य है जिसे आपको लिखना होगा; यह बिल्ट-इन नहीं है। उदाहरण के लिए, यह संभवतः उस मॉड्यूल के अनुरूप फ़ाइल को खोल सकता है जिसे आप आयात कर रहे हैं और इसे कैश्ड संस्करण के साथ अलग कर सकते हैं यह देखने के लिए कि क्या यह बदल गया है।
जेम्स मचघ

252

पायथन 3.0-3.3 में आप का उपयोग करेंगे: imp.reload(module)

BDFL है जवाब इस सवाल का।

हालाँकि, imp3.4 में पदावनत किया गया था,importlib (धन्यवाद @Stefan! ) के पक्ष में

मुझे लगता है , इसलिए, अब आप उपयोग करेंगे importlib.reload(module), हालांकि मुझे यकीन नहीं है।


23
बयाना नौसिखिया अजगर 2 और 3 के बीच महत्वपूर्ण बारीकियों के बारे में जानने के लिए आभारी है
Smandoli

24
imp.reload (imp) मान्य है?
Lo11c Faure-Lacroix

2
@ Lo @cFaure-Lacroix उसी तरह reload(__builtins__)से 2.x में मान्य है
Jernernardo

1
@ टार्च: यह पायथन मॉड्यूल है जिसे आप पुनः लोड करना चाहते हैं, जैसे प्रश्न में उदाहरण।
पॉल डी। वेट

3
@ Lo @cFaure-Lacroix हाँ, छोटा सा भूत खुद को फिर से लोड कर सकता है।
डेविन कोलियर जॉनसन

92

एक मॉड्यूल को हटाना विशेष रूप से मुश्किल हो सकता है यदि यह शुद्ध पायथन नहीं है।

यहाँ से कुछ जानकारी है: मैं वास्तव में एक आयातित मॉड्यूल को कैसे हटाऊं?

आप संदर्भों की वास्तविक संख्या का पता लगाने के लिए sys.getrefcount () का उपयोग कर सकते हैं।

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

3 से अधिक संख्याएं इंगित करती हैं कि मॉड्यूल से छुटकारा पाना मुश्किल होगा। घरेलू "खाली" (कुछ भी नहीं) मॉड्यूल के बाद कचरा एकत्र किया जाना चाहिए

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

तीसरे संदर्भ के रूप में getrefcount () फ़ंक्शन की एक कलाकृति है।


4
मुझे अभी पता चला है कि यदि मॉड्यूल एक पैकेज का एक हिस्सा है, तो आपको इसे वहां भी हटाना होगा:setattr(package, "empty", None)
u0b34a0f6ae

6
यह सही समाधान है, खासकर यदि आपके पास नेस्टेड मॉड्यूल वाला पैकेज है। reload()केवल शीर्ष-सबसे मॉड्यूल को पुनः लोड करता है, और इसके अंदर कुछ भी पुनः लोड नहीं किया जाएगा जब तक कि आप इसे पहले sys.modules से हटा नहीं देते हैं।
सेरिन

73

reload(module), लेकिन केवल अगर यह पूरी तरह से अकेला है। यदि किसी और चीज में मॉड्यूल (या मॉड्यूल से संबंधित कोई वस्तु) का संदर्भ है, तो आपको पुराने कोड के कारण सूक्ष्म और जिज्ञासु त्रुटियां मिलेंगी जो आपकी अपेक्षा से अधिक समय तक लटकी रहती हैं, और isinstanceविभिन्न संस्करणों में काम नहीं करने जैसी चीजें एक ही कोड।

यदि आपके पास एक-तरफ़ा निर्भरताएँ हैं, तो आपको पुराने मॉड्यूल के सभी संदर्भों से छुटकारा पाने के लिए सभी मॉड्यूलों को पुनः लोड करना होगा जो पुनः लोड किए गए मॉड्यूल पर निर्भर करते हैं। और फिर पुनः लोड मॉड्यूल जो पुनः लोड किए गए मॉड्यूल पर निर्भर करता है, पुनरावर्ती।

यदि आपके पास परिपत्र निर्भरता है, जो उदाहरण के लिए बहुत आम है जब आप पैकेज को फिर से लोड करने के साथ काम कर रहे हैं, तो आपको समूह के सभी मॉड्यूल को एक बार में लोड करना होगा। आप इसके साथ ऐसा नहीं कर सकते reload()क्योंकि यह प्रत्येक मॉड्यूल को फिर से आयात करेगा इससे पहले कि उसकी निर्भरता ताज़ा हो, पुराने संदर्भों को नए मॉड्यूल में रेंगने की अनुमति देता है।

इस मामले में ऐसा करने का एकमात्र तरीका हैक करना है sys.modules, जो कि असमर्थित है। आपको उस प्रत्येक sys.modulesप्रविष्टि से गुजरना और हटाना होगा जिसे आप अगले आयात पर फिर से लोड करना चाहते थे, और उन प्रविष्टियों को भी हटा सकते हैं जिनके मूल्य हैंNone क्रियान्वित करने के मुद्दे से निपटने के लिए कैशिंग के सापेक्ष असफल आयात के साथ करना है। यह बहुत अच्छा नहीं है, लेकिन जब तक आपके पास पूरी तरह से आत्म निर्भरता का एक सेट है जो इसके कोडबेस के बाहर संदर्भ नहीं छोड़ता है, यह काम करने योग्य है।

संभवतः सर्वर को पुनरारंभ करना सबसे अच्छा है। :-)


1
विशेष रूप से उस परिदृश्य के लिए dreload नहीं है?
जोश

@ जोश: नहीं, यह एक पैकेज ट्री को फिर से लोड करने के लिए है, और तब भी यह केवल तब तक काम करता है जब तक पैकेज के बाहर / परिपत्र निर्भरता नहीं होती है।
बोबिन्स

1
क्या आप Noneमानों के साथ भाग को विस्तृत कर सकते हैं क्योंकि मैं इस मुद्दे में बिल्कुल भाग रहा हूं: मैं आइटमों को हटा रहा हूं sys.modulesऔर पुन: आयात करने के बाद कुछ आयातित निर्भरताएं हैं None
schlamar

@shclamar: पृष्ठभूमि के लिए stackoverflow.com/questions/1958417/… (और वहां से लिंक) देखें । यह मेरे लिए स्पष्ट नहीं है (यहां तक ​​कि import.c कोड को देखते हुए) कैसे Noneप्रविष्टियों को आयात तंत्र के माध्यम से वापस लाने में कामयाब रहे जब 'वास्तविक' प्रविष्टियां हटा दी गईं, और मैं इसे 2.7 पर होने के लिए प्रतीत नहीं कर सकता; भविष्य में निश्चित रूप से यह अब समस्या नहीं है क्योंकि निहित रिश्तेदार आयात दूर हो गए हैं। इस बीच, Noneमान के साथ सभी प्रविष्टियों को हटाने से इसे ठीक करना प्रतीत होता है।
बॉब

1
@Eliethesaiyan: क्या आप reloadफ़ंक्शन का मतलब है ? यह अंतर्निहित है, आपको किसी भी पुस्तकालय को आयात करने की आवश्यकता नहीं है।
बोबिन्स

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

3
+1। मेरा लक्ष्य अजगर के भीतर नाक परीक्षण चलाने का था। जब मैंने एक मॉड्यूल लोड किया था और कुछ कार्यों का नाम बदल दिया था, तो पुराने नाम कॉल करते समय nose.run()भी बने रहे , उसके बाद भीreload(my_module) %run my_module
पीटर डी।

5
यदि आपका मॉड्यूल अपने स्वयं के सबमॉड्यूल्स आयात करता है, तो आपको उन्हें भी हटाने की आवश्यकता हो सकती है। कुछ इस तरह [del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
ड्रेविको

मुझे नहीं लगता कि मॉड्यूल को अनलोड करता है। पायथन 3.8 पर: import sys; import json; del sys.modules['json']; print(json.dumps([1]))और json मॉड्यूल अभी भी काम कर रहा है, भले ही यह sys.modules में नहीं है।
सेपरमैन

60

पायथन 2 के लिए अंतर्निहित फ़ंक्शन रीलोड () का उपयोग करें :

reload(module)

पायथन 2 और 3.2–3.3 के लिए मॉड्यूल छोटा सा भूत से पुनः लोड का उपयोग करें :

import imp
imp.reload(module)

लेकिन आयात के पक्ष में संस्करण 3.4 के बाद से imp हटा दिया गया है , इसलिए उपयोग करें:

import importlib
importlib.reload(module)

या

from importlib import reload
reload(module)

2
इनमें से किसी भी मामले को संभालने के लिए: from six import reload_module( pip install sixपाठ्यक्रम की सबसे पहले जरूरत )
Anentropic

@Anentropic: छह पैकेज का उपयोग करने की सलाह देना अच्छी बात है, लेकिन वाक्यविन्यास from six.moves import reload_module( doc )
x0s

23

निम्नलिखित कोड आपको पायथन 2/3 संगतता की अनुमति देता है:

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

आप इसे reload()दोनों संस्करणों में उपयोग कर सकते हैं जो चीजों को सरल बनाता है।


18

स्वीकृत उत्तर X आयात Y मामले से नहीं निपटता है। यह कोड इसे और मानक आयात मामले को भी संभालता है:

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

पुनः लोड करने के मामले में, हम नए पुनः लोड किए गए मॉड्यूल में संग्रहीत मूल्यों के लिए शीर्ष स्तर के नामों को फिर से असाइन करते हैं, जो उन्हें अपडेट करता है।


एक समस्या को देखते हुए, ग्लोबल्स () उस मॉड्यूल को संदर्भित करता है जिसे आप इस फ़ंक्शन को परिभाषित करते हैं, इसलिए यदि आप इसे मॉड्यूल में परिभाषित करते हैं, तो आप इसे कॉल नहीं करते हैं।
जोसेफ गार्विन

इंटरएक्टिव के लिए, >>> from X import Yपुनः लोड करने के बाद>>> __import__('X', fromlist='Y')
बॉब स्टीन

@ BobStein-VisiBone, क्या उस काम को करने का कोई तरीका है fromlist='*'?
माइक सी।

अच्छा सवाल है, @MikeC नहीं जानते। वैसे मैं fromआयात बयानों में लगभग सभी उपयोग को रोकने के लिए ट्रेंड कर रहा हूं । import <package>कोड में बस स्टार्क और स्पष्ट पैकेज। सिंबल। यह एहसास हमेशा संभव या वांछनीय नहीं हो सकता है। (यहां एक अपवाद है: भविष्य के आयात से print_function।)
बॉब स्टीन

माइक सी: मेरे लिए क्या काम करता हैfoo = reload(foo); from foo import *
रैंप

16

यह एक मॉड्यूल को फिर से लोड करने का आधुनिक तरीका है:

from importlib import reload

यदि आप 3.5 से अधिक पुराने पायथन के संस्करणों का समर्थन करना चाहते हैं, तो यह प्रयास करें:

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+

इसका उपयोग करने के लिए, उस मॉड्यूल की reload(MODULE)जगह लें MODULE, जिसे आप फिर से लोड करना चाहते हैं।

उदाहरण के लिए, मॉड्यूल reload(math)को पुनः लोड करेगा math


4
या बस करो from importlib import reload। तब आप कर सकते हैं reload(MODULE_NAME)। इस फ़ंक्शन की कोई आवश्यकता नहीं है।
'

मेरा मानना modulereload(MODULE_NAME)है कि बस की तुलना में अधिक आत्म-व्याख्यात्मक है reload(MODULE_NAME)और अन्य कार्यों के साथ संघर्ष करने का कम मौका है।
रिची बेंडल

@RichieBendall क्षमा करें, लेकिन यह उत्तर पूरी तरह से गलत है। पुनः लोड () फ़ंक्शन मॉड्यूल ऑब्जेक्ट लेता है, मॉड्यूल का नाम नहीं ... डॉक्स पढ़ें: docs.python.org/3/library/importlib.html#importlib.reload और मैं @ pault से सहमत हूं - यह "modadeload" के रूप में शानदार है ।
mbdevpl

मैंने आपकी राय को दर्शाने के लिए अपना उत्तर बदल दिया है।
रिची बेंडल

13

यदि आप एक सर्वर में नहीं हैं , लेकिन विकासशील हैं और एक मॉड्यूल को बार-बार लोड करने की आवश्यकता है, तो यहां एक अच्छी टिप है।

सबसे पहले, सुनिश्चित करें कि आप ज्यूपिटर नोटबुक परियोजना से उत्कृष्ट आईपीथॉन शेल का उपयोग कर रहे हैं । Jupyter स्थापित करने के बाद, आप इसके साथ शुरू कर सकते हैं ipython, या jupyter console, या और भी बेहतर, jupyter qtconsoleआप किसी भी ओएस में कोड पूरा होने के साथ एक अच्छा colorized सांत्वना देगा।

अब अपने शेल में टाइप करें:

%load_ext autoreload
%autoreload 2

अब, हर बार जब आप अपनी स्क्रिप्ट चलाते हैं, तो आपके मॉड्यूल पुनः लोड किए जाएंगे।

इसके अलावा 2, ऑटोरेलोड जादू के अन्य विकल्प हैं :

%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

मेरे जैसे उन लोगों के लिए जो सभी मॉड्यूल को उतारना चाहते हैं (जब Emacs के तहत पायथन दुभाषिया में चल रहे हैं ):

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

अधिक जानकारी पायथन मॉड्यूल को पुनः लोड करने में है ।


वास्तव में ऐसा लगता है कि मज़बूती से काम नहीं करता है (2.6 में) क्योंकि सब कुछ sys.modules.values()एक मॉड्यूल नहीं है। उदाहरण के लिए: >>> प्रकार (sys.modules.values ​​() [1]) <वर्ग 'email.LazyImporter'> इसलिए अगर मैं उस कोड को चलाने का प्रयास करता हूं तो वह गिर जाता है (मुझे पता है कि इसका व्यावहारिक हल नहीं है, बस इशारा करते हुए कहा कि)।
फ्रांसिस डेवी

यह पहले के अजगर में भी काम नहीं करता है - जैसा कि लिखा गया है। मुझे कुछ नामों को छोड़ना पड़ा। जब मैं उस कोड को अपने नए कंप्यूटर पर ले जाऊंगा तो मैं पोस्ट अपडेट कर दूंगा।

2
कुछ संशोधनों के बाद पायथन 2.7 में ठीक काम करता है:if mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak

2
यह मेरे लिए अच्छा काम करता है: sys.modules.values ​​() में m के लिए [reload (m) आयात करें, अगर m में। M नाम और नहीं " " नाम में और imp.is_builtin (m .__ name__)]
पैट्रिक वुल्फ

5

उत्साहित लक्षण में एक मॉड्यूल है जो इसके लिए काफी अच्छी तरह से काम करता है। https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

यह बदले गए किसी भी मॉड्यूल को फिर से लोड करेगा, और अन्य मॉड्यूल और अस्थिर वस्तुओं को अपडेट करेगा जो इसका उपयोग कर रहे हैं। यह अधिकांश समय __very_private__विधियों के साथ काम नहीं करता है , और क्लास इनहेरिटेंस पर चोक कर सकता है, लेकिन यह मुझे पागल समय को होस्ट एप्लिकेशन को फिर से शुरू करने से बचाता है, जब PyQt guis, या सामान जो माया या Nuke जैसे प्रोग्राम के अंदर चलता है, लिखता है। यह समय के 20-30% शायद काम नहीं करता है, लेकिन यह अभी भी अविश्वसनीय रूप से उपयोगी है।

उत्साहित पैकेज ने उन क्षणों को फिर से लोड नहीं किया है जो वे बदलते हैं - आपको इसे स्पष्ट रूप से कॉल करना होगा - लेकिन यह सब लागू करने के लिए कठिन नहीं होना चाहिए अगर आपको वास्तव में इसकी आवश्यकता है


5

जो अजगर 3 का उपयोग कर रहे हैं और आयात से पुनः लोड करते हैं।

यदि आपको ऐसी समस्याएँ हैं, तो ऐसा लगता है कि मॉड्यूल पुनः लोड नहीं करता है ... ऐसा इसलिए है क्योंकि इसे pyc (60 सेकंड तक) recompile करने के लिए कुछ समय चाहिए। मैं यह संकेत केवल इसलिए लिख रहा हूं कि आप जानते हैं कि क्या आपने इस तरह की समस्या का अनुभव किया है।



3

दूसरा विकल्प। देखें कि पायथन डिफॉल्ट importlib.reloadसिर्फ एक तर्क के रूप में पारित पुस्तकालय को फिर से आयात करेगा। यह उन पुस्तकालयों को पुनः लोड नहीं करेगा , जो आपके आयात का आयात करते हैं। यदि आपने बहुत सी फाइलें बदली हैं और आयात करने के लिए कुछ जटिल पैकेज हैं, तो आपको एक गहरा पुनः लोड करना होगा

यदि आपके पास IPython या Jupyter स्थापित है, तो आप एक फ़ंक्शन का उपयोग सभी कामों को फिर से लोड करने के लिए कर सकते हैं:

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

यदि आपके पास जुपिटर नहीं है, तो इसे अपने शेल में इस कमांड के साथ इंस्टॉल करें:

pip3 install jupyter

इंपीलिब से यह इफ्थॉन ड्रेलोड और रीलोड (दोनों) के साथ शिकायत करता है reload() argument must be module। मैं एक कस्टम फंक्शन इम्पोर्ट का उपयोग कर रहा हूं और काम नहीं कर रहा हूं। अंतर्निहित मॉड्यूल का उपयोग करना काम करता है। :-( यह समय की बर्बादी है कि मैं अपने कोड में किए गए हर छोटे बदलाव के लिए iPython को फिर से लोड कर रहा हूं ...
m3nda

2

संपादित करें (उत्तर V2)

पहले से समाधान केवल रीसेट जानकारी प्राप्त करने के लिए अच्छा है, लेकिन यह सभी संदर्भों को नहीं बदलेगा (अधिक से अधिक reloadलेकिन फिर कम आवश्यक)। वास्तव में सभी संदर्भ सेट करने के लिए, मुझे कचरा कलेक्टर में जाना था, और वहां के संदर्भों को फिर से लिखना था। अब यह एक आकर्षण की तरह काम करता है!

ध्यान दें कि यह काम नहीं करेगा यदि GC बंद है, या यदि GC द्वारा निगरानी नहीं की गई डेटा को पुनः लोड कर रहा है। यदि आप GC के साथ गड़बड़ नहीं करना चाहते हैं, तो मूल उत्तर आपके लिए पर्याप्त हो सकता है।

नया कोड:

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)

मूल उत्तर

जैसा कि @ bobince के उत्तर में लिखा गया है, अगर पहले से ही किसी अन्य मॉड्यूल में उस मॉड्यूल का संदर्भ है (विशेषकर अगर यह asकीवर्ड जैसे आयात किया गया था import numpy as np), तो वह उदाहरण ओवरराइट नहीं किया जाएगा।

यह मेरे लिए काफी समस्याग्रस्त साबित हुआ, जब कि विन्यास मॉड्यूल के एक "क्लीन-स्लेट" राज्य आवश्यक परीक्षणों को लागू करने, इसलिए मैं नाम के एक समारोह में लिखा है reset_moduleका उपयोग करता है कि importlibके reloadसमारोह और रिकर्सिवली सभी घोषित मॉड्यूल के गुणों को अधिलेखित करता है। इसका परीक्षण पायथन संस्करण 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

नोट: देखभाल के साथ प्रयोग करें! गैर-परिधीय मॉड्यूल (उदाहरण के लिए बाहरी रूप से उपयोग की जाने वाली कक्षाओं को परिभाषित करने वाले मॉड्यूल) पर इनका उपयोग करने से पायथन में आंतरिक समस्याएं हो सकती हैं (जैसे कि अचार / अन-पिकिंग मुद्दे)।


1

मेरे लिए अबैकस के मामले में यह काम करने का तरीका है। कल्पना करें कि आपकी फ़ाइल 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'])

यह उत्तर यहाँ से एक सीधी प्रति है: ebanshi.cc/questions/1942/…
SiHa

0

मुझे Sublime Text के अंदर कुछ फिर से लोड करने की कोशिश करने में बहुत परेशानी हुई, लेकिन आखिरकार मैं कोड उपयोगिता के आधार पर Sublime पाठ पर पुनः लोड मॉड्यूल को पुनः लोड करने के लिए इस उपयोगिता को लिख सकता था sublime_plugin.py

यह नीचे आपको उनके नाम पर रिक्त स्थान वाले रास्तों से मॉड्यूल को फिर से लोड करने के लिए स्वीकार करता है, फिर बाद में पुनः लोड करने के बाद आप बस आयात कर सकते हैं जैसा कि आप आमतौर पर करते हैं।

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

यदि आप पहली बार चलाते हैं, तो इसे मॉड्यूल को लोड करना चाहिए, लेकिन अगर बाद में आप फिर से विधि / कार्य कर सकते हैं तो run_tests()यह परीक्षण फ़ाइलों को फिर से लोड करेगा। Sublime Text ( Python 3.3.6) के साथ यह बहुत होता है क्योंकि इसका दुभाषिया कभी बंद नहीं होता है (जब तक आप Sublime Text को पुनः आरंभ नहीं करते हैं, यानी Python3.3दुभाषिया)।


-1

एक अन्य तरीका एक फ़ंक्शन में मॉड्यूल आयात करना हो सकता है। इस तरह जब फ़ंक्शन पूरा होता है, तो मॉड्यूल कचरा एकत्र हो जाता है।


4
मॉड्यूल को कचरा एकत्र नहीं किया जाएगा क्योंकि एक वैश्विक संदर्भ कम से कम में आयोजित किया जाता है sys.modules
सभी श्रमिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.