पायथन: 'एक्स एक्स आयात वाई' से आयात किए गए घटक वाई को पुनः लोड करें?


91

पायथन में, एक बार जब मैंने एक दुभाषिया सत्र में मॉड्यूल एक्स का उपयोग करके आयात किया है import X, और बाहर की तरफ मॉड्यूल बदलता है, तो मैं मॉड्यूल को फिर से लोड कर सकता हूं reload(X)। तब परिवर्तन मेरे दुभाषिया सत्र में उपलब्ध हो जाते हैं।

मैं सोच रहा था कि क्या यह भी संभव है जब मैं मॉड्यूल एक्स से एक घटक वाई का उपयोग कर आयात करता हूं from X import Y

बयान reload Yकाम नहीं करता है, क्योंकि वाई खुद एक मॉड्यूल नहीं है, लेकिन केवल एक घटक (इस मामले में एक वर्ग) एक मॉड्यूल के अंदर।

क्या दुभाषिया सत्र को छोड़कर (या पूरे मॉड्यूल को आयात किए बिना) मॉड्यूल के अलग-अलग घटकों को फिर से लोड करना संभव है?

संपादित करें:

स्पष्टीकरण के लिए, सवाल एक मॉड्यूल एक्स से एक वर्ग या फ़ंक्शन वाई को आयात करने और एक परिवर्तन पर फिर से लोड करने के बारे में है, न कि पैकेज एक्स से एक मॉड्यूल वाई।


मेरा मानना ​​है कि इस प्रश्न में एक विरोधाभास है: " ... possible ... import a component Y from module X" बनाम " question is ... importing a class or function X from a module Y"। मैं उस प्रभाव को संपादित कर रहा हूं।
कैटस्कुल

ऐसा प्रतीत होता है कि चिह्नित उत्तर वास्तव में प्रश्न का उत्तर नहीं देता है, मेरा मानना ​​है कि मेरा करता है। क्या आप अपडेट / टिप्पणी कर सकते हैं?
कैटस्कुल

जवाबों:


49

यदि Y एक मॉड्यूल है (और X एक पैकेज) reload(Y)ठीक है - अन्यथा, आप देखेंगे कि क्यों अच्छा पायथन स्टाइल गाइड (जैसे कि मेरे नियोक्ता) एक मॉड्यूल को छोड़कर कुछ भी आयात करने के लिए कभी नहीं कहते हैं (यह कई महान कारणों में से एक है - फिर भी लोग अभी भी फ़ंक्शंस और क्लासेस को सीधे आयात करते रहते हैं, चाहे मैं कितना भी समझाऊं कि यह एक अच्छा विचार नहीं है ; ;-)


1
में तुम्हारी बात समझ रहा हूँ। क्या आप किसी अन्य अच्छे कारणों पर विस्तार से ध्यान देंगे कि यह एक अच्छा विचार क्यों नहीं है?
cschol

6
@cschol: पायथन का ज़ेन, अंतिम कविता ( import thisइंटरैक्टिव संकेत से अजगर के ज़ेन को देखने के लिए); और सभी कारण क्यों नामस्थान एक महान विचार है (तत्काल स्थानीय दृश्य सुराग कि नाम देखा जा रहा है, परीक्षण में मज़ाक / इंजेक्शन लगाने में आसानी, पुनः लोड करने की क्षमता, एक मॉड्यूल के लिए अपनी प्रविष्टियों को पूर्वनिर्धारित करके लचीले ढंग से बदलने की क्षमता, पूर्वानुमान और नियंत्रणीय अपने डेटा के क्रमांकन और पुनर्प्राप्ति पर व्यवहार [[अचार और अनपैकिंग द्वारा]], और इसी तरह, और आगे - एक SO टिप्पणी शायद ही इस समृद्ध, लंबे तर्क के साथ न्याय करने के लिए पर्याप्त है !!!)
एलेक्स मार्टेली

4
ध्यान दें कि पायथन 3 में, रीलोड अब डिफ़ॉल्ट नामस्थान में नहीं है, लेकिन importlibपैकेज में ले जाया गया है। importlib.reload(Y) docs.python.org/3.4/library/… यह भी देखें stackoverflow.com/questions/961162/…
मक्खियों

4
@ थोरसुमोनर, बिल्कुल नहीं - इसका मतलब है "हमेशा आयात मॉड्यूल", इसलिए "my.package आयात mymodule से" बिल्कुल ठीक है और वास्तव में पसंद किया जाता है - बस, कभी आयात वर्ग, कार्य, आदि - हमेशा, केवल, कभी मॉड्यूल
एलेक्स मार्टेली

2
Downvote। क्यों? यह सही उत्तर नहीं है। सही जवाब Catskul ने Jul 30 '12 को 15:04 पर दिया।
meh

102

उत्तर

मेरे परीक्षणों से, चिह्नित उत्तर, जो एक सरल सुझाव देता है reload(X), काम नहीं करता है।

मैं जो सही उत्तर बता सकता हूं, वह है:

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y

परीक्षा

मेरा परीक्षण निम्नलिखित था (पायथन 2.6.5 + बेफथॉन 0.9.5.2)

X.py:

def Y():
    print "Test 1"

bpython:

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after

1
वाह। मुझे यह वास्तव में आसान लगा। धन्यवाद! मैं इसे अब एक लाइनर के रूप में उपयोग करता हूं: आयात X; पुनः लोड (एक्स); X आयात Y से
otterb

1
यह स्वीकृत उत्तर की तुलना में बेहतर उत्तर है। लोगों को चेतावनी देना उचित है, लेकिन हर किसी के उपयोग का मामला अलग है। कुछ मामलों में यह वास्तव में एक वर्ग को फिर से लोड करने में सहायक होता है, उदाहरण के लिए जब आप अजगर कंसोल का उपयोग कर रहे हैं और अपने सत्र को खोए बिना अपने कोड में परिवर्तन लोड करना चाहते हैं।
निक

यह हमेशा काम नहीं करता है। मेरे पास एक मॉड्यूल है Fooजिसमें __init__.pyएक सबमॉडल है, जो मैं एक प्रतिसाद के रूप में पोस्ट करूंगा।
जेसन एस

पायथन 3 एक लाइनर अब: आयात आयात, आयात एक्स; importlib.reload (X); X आयात Y से
वेन

12
from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func

यह सबसे अच्छा तरीका है, क्योंकि आपको याद नहीं होगा कि यह कैसे आयात किया गया था
portforwardpodcast

यह मूल प्रश्न का एकमात्र कार्यशील समाधान है, और इसमें बहुत कम वोट हैं!
चार्ल्सब

1
अजगर में 3 जोड़ें: importlib आयात पुनः लोड से
mirek

7

सबसे पहले, आपको पुनः लोड का उपयोग नहीं करना चाहिए, यदि आप इससे बच सकते हैं। लेकिन मान लें कि आपके पास अपने कारण हैं (यानी IDLE के अंदर डिबगिंग)।

पुस्तकालय को पुनः लोड करने से मॉड्यूल के नामस्थान में नाम वापस नहीं आएंगे। ऐसा करने के लिए, बस चर को फिर से असाइन करें:

f = open('zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()

from zoo import snakes
print snakes

f = open('zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()

import zoo
reload(zoo)
snakes = zoo.snakes # the variable 'snakes' is now reloaded

print snakes

आप इसे कुछ अन्य तरीकों से कर सकते हैं। आप स्थानीय नाम स्थान के माध्यम से खोज कर, और किसी भी चीज़ को फिर से असाइन कर सकते हैं, जो कि मॉड्यूल से था, लेकिन मुझे लगता है कि हम काफी बुरे हो रहे हैं।


4

यदि आप ऐसा करना चाहते हैं:

from mymodule import myobject

इसके बजाय यह करें:

import mymodule
myobject=mymodule.myobject

आप अब उसी तरह से myobject का उपयोग कर सकते हैं जैसे आप योजना बना रहे थे (हर जगह बिना थके अप्रमाणित मायोड्यूले संदर्भों के)।

यदि आप अंतःक्रियात्मक रूप से काम कर रहे हैं और आप अब उपयोग कर सकने वाले mymodule से myobject को पुनः लोड करना चाहते हैं:

reload(mymodule)
myobject=mymodule.myobject

2

यह मानते हुए कि आपके from X import Yपास दो विकल्प हैं:

reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module

या

Y=reload(sys.modules['X']).Y

कुछ विचार:

A. यदि आयात गुंजाइश मॉड्यूल-वाइड (ई, जी: एक फ़ंक्शन में आयात) नहीं है - तो आपको दूसरे संस्करण का उपयोग करना होगा।

ख। यदि Y को दूसरे मॉड्यूल (Z) से X में आयात किया जाता है - तो आपको Z को फिर से लोड करना होगा, X को पुनः लोड करने से और अपने मॉड्यूल को फिर से लोड करने से, यहां तक ​​कि अपने सभी मॉड्यूल को पुनः लोड करना होगा (e, g: [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]use) Z को पुनः लोड करने से पहले X को पुनः लोड कर सकता है - और से वाई के मूल्य को ताज़ा नहीं करते।


1
  1. reload()मॉड्यूल X,
  2. reload()Yसे आयात मॉड्यूल X

ध्यान दें कि पुनः लोड करना पहले से ही अन्य नामस्थानों में बंधी हुई वस्तुओं को नहीं बदलेगा (भले ही आप एलेक्स से शैली गाइड का पालन करें)।


1

यदि आप एक jupyter वातावरण में काम कर रहे हैं, और आप पहले से ही है from module import functionजादू समारोह का उपयोग कर सकते autoreloadद्वारा

%load_ext autoreload
%autoreload
from module import function

autoreloadIPython की शुरूआत यहां दी गई है


0

सिर्फ एलेक्समार्टेली के और कैट्सकुल के जवाबों का पालन ​​करने के लिए , वास्तव में कुछ सरल लेकिन बुरे मामले हैं जो reloadकम से कम पाइथन 2 में भ्रमित होते हैं ।

मान लीजिए कि मेरे पास निम्नलिखित स्रोत वृक्ष हैं:

- foo
  - __init__.py
  - bar.py

निम्नलिखित सामग्री के साथ:

init.py:

from bar import Bar, Quux

bar.py:

print "Loading bar"

class Bar(object):
  @property
  def x(self):
     return 42

class Quux(Bar):
  object_count = 0
  def __init__(self):
     self.count = self.object_count
     self.__class__.object_count += 1
  @property
  def x(self):
     return super(Quux,self).x + 1
  def __repr__(self):
     return 'Quux[%d, x=%d]' % (self.count, self.x)

यह उपयोग किए बिना ठीक काम करता है reload:

>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]

लेकिन पुनः लोड करने का प्रयास करें और इसका कोई प्रभाव नहीं पड़ता है या चीजों को नष्ट नहीं करता है:

>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module 'foo' from 'foo\__init__.pyc'>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module 'foo.bar' from 'foo\bar.pyc'>
>>> Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8

एकमात्र तरीका जिससे मैं यह सुनिश्चित कर सका कि barसबमॉड्यूल को फिर से लोड किया गया था reload(foo.bar); जिस तरह से मैं फिर से लोड किए गए Quuxवर्ग तक पहुंचता हूं, उसे फिर से लोड किए गए उप मॉड्यूल से पहुंचना और पकड़ना है; लेकिन fooमॉड्यूल खुद को मूल Quuxवर्ग ऑब्जेक्ट पर रखता था , संभवतः क्योंकि यह उपयोग करता है from bar import Bar, Quux(बजाय import barइसके बाद Quux = bar.Quux); इसके अलावा Quuxवर्ग खुद के साथ सिंक से बाहर हो गया, जो कि सिर्फ विचित्र है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.