পাইথন: পুনরায় লোড উপাদান Y এক্সপোর্ট এক্স এক্স ইমেজ দিয়ে?


96

পাইথনে, আমি একবার ব্যবহার করে দোভাষী সেশনে একটি মডিউল এক্স আমদানি করেছিলাম import Xএবং মডিউলটি বাইরের দিকে পরিবর্তিত হয়ে আমি মডিউলটি পুনরায় লোড করতে পারি reload(X)। তারপরে পরিবর্তনগুলি আমার দোভাষী সেশনে উপলভ্য হয়।

আমি ভাবছি যে আমি যখন মডিউল এক্স ব্যবহার করে কোনও উপাদান Y আমদানি করি তখন এটিও সম্ভব from X import Y

বিবৃতিটি কার্যকর reload Yহয় না, যেহেতু ওয়াই নিজেই মডিউল নয়, তবে একটি মডিউলের ভিতরে কেবল একটি উপাদান (এই ক্ষেত্রে একটি শ্রেণি)।

দোভাষীর অধিবেশন (বা পুরো মডিউলটি আমদানি না করে) কোনও মডিউলের পৃথক উপাদানগুলি পুনরায় লোড করা কি আদৌ সম্ভব?

সম্পাদনা:

স্পষ্টতার জন্য, প্রশ্নটি হল মডিউল এক্স থেকে ক্লাস বা ফাংশন ওয়াই আমদানি করা এবং প্যাকেজ এক্স থেকে মডিউল ওয়াই নয়, পরিবর্তনের উপর পুনরায় লোড করা is


আমি বিশ্বাস করি এই প্রশ্নে একটি বৈপরীত্য রয়েছে: " ... possible ... import a component Y from module X" বনাম " question is ... importing a class or function X from a module Y"। আমি সেই প্রভাবটিতে একটি সম্পাদনা যুক্ত করছি।
ক্যাটসকুল

দেখা যাচ্ছে যে চিহ্নিত উত্তরটি আসলে প্রশ্নের উত্তর দেয় না, আমি বিশ্বাস করি আমার কাজটি করে। আপনি আপডেট / মন্তব্য করতে পারেন?
ক্যাটসকুল

উত্তর:


51

যদি ওয়াই মডিউল হয় (এবং এক্স একটি প্যাকেজ) reload(Y)ঠিক আছে - অন্যথায়, আপনি দেখতে পাবেন কেন ভাল পাইথন স্টাইল গাইড (যেমন আমার নিয়োগকর্তার) মডিউল ছাড়া কোনও কিছুই আমদানি করতে কেন বলেন না (এটি অনেক দুর্দান্ত কারণগুলির মধ্যে একটি) - এখনো মানুষ এখনো আমি কত ব্যাখ্যা এটাই সরাসরি কার্যকারিতা ও শ্রেণীর আমদানি রাখা, সেটা ব্যাপার না একটি ভাল ধারণা ;-)।


4
আমি আপনার পয়েন্ট দেখুন. কেন আপনি যে কোনও ভাল কারণ এটি একটি ভাল ধারণা নয় তা ব্যাখ্যা করার যত্ন নেবেন?
cschol

6
@ সিএসচল: পাইথনের জেন, শেষ আয়াত ( import thisপাইথনের জেন দেখার জন্য ইন্টারেক্টিভ প্রম্পট থেকে); এবং নেমস্পেসগুলি কেন একটি সম্মানজনক দুর্দান্ত ধারণা (তাত্ক্ষণিক স্থানীয় ভিজ্যুয়াল ক্লু যে নামটি সন্ধান করা হচ্ছে, পরীক্ষায় ঠাট্টা করা / ইনজেকশন করা সহজ, পুনরায় লোড করার ক্ষমতা, কিছু এন্ট্রি পুনরায় সংজ্ঞায়িত করে মডিউলটির নমনীয়ভাবে পরিবর্তন করার ক্ষমতা, ভবিষ্যদ্বাণীযোগ্য এবং নিয়ন্ত্রণযোগ্য) আপনার ডেটা সিরিয়ালাইজেশন এবং পুনরুদ্ধারের উপর আচরণ [[যেমন: বাছাই এবং আন-পিক্লিং দ্বারা]] এবং আরও অনেক কিছু - এই ধনী, দীর্ঘ যুক্তির সাথে ন্যায়বিচার করার পক্ষে একটি এসও মন্তব্য খুব দীর্ঘ নয় !!! -)
অ্যালেক্স মার্টেলি

4
দ্রষ্টব্য যে পাইথন 3-এ, পুনরায় লোড আর ডিফল্ট নেমস্পেসে নেই তবে importlibপ্যাকেজে স্থানান্তরিত হয়েছে । importlib.reload(Y) docs.python.org/3.4/library/... আরও দেখুন stackoverflow.com/questions/961162/...
উড়ে

4
@ থারস্মমনার, একেবারেই নয় - এর অর্থ "সর্বদা মডেলগুলি আমদানি করুন", সুতরাং "মাইপ্যাকেজ আমদানি মাইমোডুল থেকে" একেবারে সূক্ষ্ম এবং প্রকৃতপক্ষে পছন্দসই - কখনও কখনও ক্লাস, ফাংশন ইত্যাদি আমদানি করেন না - সর্বদা, কেবল, কখনও মডিউল
অ্যালেক্স মার্টেলি

4
ডাউনভোট কেন? এটি সঠিক উত্তর নয়। সঠিক উত্তরটি ক্যাটস্কুল 30 জুলাই '12 এ 15:04 এ দিয়েছেন।
meh

105

উত্তর

আমার পরীক্ষাগুলি থেকে, চিহ্নিত উত্তরটি, যা একটি সাধারণ প্রস্তাব দেয় reload(X), কাজ করে না।

আমি সঠিক উত্তরটি যা বলতে পারি তা থেকে:

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

পরীক্ষা

আমার পরীক্ষাটি নিম্নলিখিতটি ছিল (পাইথন ২.6.৫ + বিপিথন ০.৯.৫.২)

এক্স.পি:

def Y():
    print "Test 1"

বিপিথন:

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

4
কি দারুন. আমি এটি সত্যিই খুব সুবিধাজনক খুঁজে পেয়েছি। ধন্যবাদ! আমি এখন এটি একটি লাইনার হিসাবে ব্যবহার করি: এক্স আমদানি করুন; পুনরায় লোড (এক্স); এক্স আমদানি ওয়াই থেকে
ওটারবাগ

4
এটি গৃহীত উত্তরটির চেয়ে উত্তম উত্তর। লোকদের সতর্ক করা এগুলি ন্যায়সঙ্গত, তবে প্রত্যেকের ব্যবহারের ক্ষেত্রে বিষয়টি আলাদা। কিছু ক্ষেত্রে ক্লাসটি পুনরায় লোড করা সত্যিই সহায়ক eg
nicb

4
এটি সবসময় কাজ করে বলে মনে হয় না। আমার একটি মডিউল রয়েছে Fooযা __init__.pyএকটি সাবমডিউলটি নিয়ে আসে ... আমি একটি উত্তর পোস্ট করে একটি উত্তর পোস্ট করব।
জেসন এস

পাইথন 3 এখন একটি লাইনার: আমদানি করুন আমদানি এক্স; আমদানি এক্স; Importlib.reload (এক্স); এক্স আমদানি ওয়াই থেকে
ওয়েইন

12
from modulename import func

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

এটিই সেরা উপায় ইমো কারণ আপনি সম্ভবত এটি কীভাবে আমদানি করা হয়েছে তা মনে করতে পারেন না
Portforwardpodcast

এটিই মূল প্রশ্নের একমাত্র কার্যকরী সমাধান এবং এর খুব কম ভোট রয়েছে!
চার্লসবি

4
অজগর 3 যুক্ত করুন: আমদানি আমদানি পুনরায় লোড থেকে
মিরেক

6

প্রথমত, আপনি যদি এড়াতে পারেন তবে আপনার পুনরায় লোডটি ব্যবহার করা উচিত নয়। তবে ধরে নেওয়া যাক আপনার কারণ রয়েছে (যেমন আইডলির ভিতরে ডিবাগিং)।

লাইব্রেরিটি পুনরায় লোড করা নামগুলি মডিউলটির নামস্থানে ফিরে পাবে না। এটি করার জন্য, কেবল ভেরিয়েবলগুলি পুনরায় নিয়োগ করুন:

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

আপনি এখন মাইবজেক্টটি একইভাবে ব্যবহার করতে পারবেন যেমন আপনি পরিকল্পনা করেছিলেন (সর্বত্র ক্লান্তিকর অপঠনযোগ্য মাইমডিউল উল্লেখ ছাড়াই)।

আপনি যদি ইন্টারেক্টিভভাবে কাজ করে থাকেন এবং মাইমডিউল থেকে মাইবজেক্টটি পুনরায় লোড করতে চান আপনি এখন ব্যবহার করতে পারেন:

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

কয়েকটি বিবেচনা:

উ: যদি আমদানির সুযোগটি মডিউল-প্রশস্ত নয় (e, g: কোনও ফাংশনে আমদানি) - আপনাকে অবশ্যই দ্বিতীয় সংস্করণটি ব্যবহার করতে হবে।

বি। যদি Y অন্য X মডিউল (জেড) থেকে এক্সে আমদানি করা হয় - আপনার অবশ্যই জেডটি পুনরায় লোড করতে হবে, এক্স পুনরায় লোডের চেয়ে বেশি এবং আপনার মডিউলটি পুনরায় লোড করতে হবে, এমনকি আপনার সমস্ত মডিউল পুনরায় লোড করা (ই, জি: ব্যবহার [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]) জেড পুনরায় লোড করার আগে এক্স পুনরায় লোড করতে পারে - এবং তার চেয়ে বেশি Y এর মান রিফ্রেশ করবেন না


1
  1. reload()মডিউল X,
  2. reload()মডিউল Yথেকে আমদানি করা X

নোট করুন যে পুনরায় লোডিং অন্য নামপত্রে আবদ্ধ ইতিমধ্যে তৈরি করা অবজেক্টগুলিকে পরিবর্তন করবে না (এমনকি আপনি যদি অ্যালেক্সের স্টাইল গাইড অনুসরণ করেন)।


1

আপনি যদি একটি ঝকঝকে পরিবেশে কাজ করছেন, এবং ইতিমধ্যে আপনার দ্বারা from module import functionযাদু ফাংশনটি ব্যবহার করতে পারেনautoreload

%load_ext autoreload
%autoreload
from module import function

autoreloadআইপিথনে ইনটির ভূমিকা এখানে দেওয়া হল ।


0

অ্যালেক্সমার্টেলির এবং ক্যাটসকুলের উত্তরগুলি অনুসরণ করার জন্য , কিছু সত্যই সহজ কিন্তু দুষ্টু মামলা রয়েছে যা reloadকমপক্ষে পাইথন ২-এ বিভ্রান্ত হওয়ার মতো ঘটেছে।

ধরুন আমার কাছে নিম্নলিখিত উত্স গাছ রয়েছে:

- foo
  - __init__.py
  - bar.py

নিম্নলিখিত বিষয়বস্তু সহ:

init.py:

from bar import Bar, Quux

বার.পি:

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ক্লাসটি নিজের সাথে সিঙ্কের বাইরে চলে গেল, যা কেবল উদ্ভট।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.