আমার দীর্ঘকাল ধরে চলছে পাইথন সার্ভার এবং সার্ভারটি পুনরায় চালু না করে কোনও পরিষেবা আপগ্রেড করতে সক্ষম হতে চাই। এটি করার সর্বোত্তম উপায় কী?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
আমার দীর্ঘকাল ধরে চলছে পাইথন সার্ভার এবং সার্ভারটি পুনরায় চালু না করে কোনও পরিষেবা আপগ্রেড করতে সক্ষম হতে চাই। এটি করার সর্বোত্তম উপায় কী?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
উত্তর:
ইতিমধ্যে বিল্টিনreload
ফাংশন (পাইথন ৩.৪++) ব্যবহার করে কোনও মডিউল আমদানি করা হলে আপনি পুনরায় লোড করতে পারেন :
from importlib import reload
import foo
while True:
# Do some things.
if is_changed(foo):
foo = reload(foo)
পাইথন 3-এ, মডিউলে reload
সরানো হয়েছিল imp
। ৩.৪-তে, imp
অনুকূলে অবহেলিত ছিল importlib
এবং reload
পরে যুক্ত করা হয়েছিল। 3 বা তারপরে লক্ষ্যবস্তু করার সময়, কল করার সময় উপযুক্ত মডিউলটি উল্লেখ করুন reload
বা এটি আমদানি করুন।
আমি মনে করি আপনি এটি চান এটি। জ্যাঙ্গোর বিকাশের সার্ভারের মতো ওয়েব সার্ভারগুলি এটি ব্যবহার করে যাতে আপনি নিজের কোড পরিবর্তনের প্রভাবগুলি সার্ভার প্রক্রিয়াটি পুনরায় আরম্ভ না করে দেখতে পারেন।
দস্তাবেজগুলি থেকে উদ্ধৃতি দিতে:
পাইথন মডিউলগুলির কোডটি পুনরায় সংযুক্ত করা হয় এবং মডিউল স্তরের কোডটি পুনরায় সাজানো হয়, মডিউলটির অভিধানে নামের সাথে আবদ্ধ হওয়া বস্তুর একটি নতুন সেট নির্ধারণ করে। এক্সটেনশন মডিউলগুলির init ফাংশনটিকে দ্বিতীয়বার বলা হয় না। পাইথনের অন্যান্য সমস্ত অবজেক্টের মতো পুরানো অবজেক্টগুলি কেবল তাদের রেফারেন্স গণনা শূন্যে নেমে যাওয়ার পরে পুনরুদ্ধার করা হয়। মডিউল নামের জায়গার নামগুলি কোনও নতুন বা পরিবর্তিত বস্তুর দিকে নির্দেশ করতে আপডেট করা হয়। পুরানো অবজেক্টের অন্যান্য রেফারেন্স (যেমন মডিউলটির বাহ্যিক নাম) নতুন বিষয়গুলির উল্লেখ করতে প্রত্যাবর্তনযোগ্য নয় এবং প্রতিটি নাম-স্থানে আপডেট করতে হবে যেখানে এটি পছন্দসই হলে তা ঘটে।
যেমন আপনি আপনার প্রশ্নে উল্লেখ করেছেন, ক্লাসটি মডিউলটিতে Foo
থাকলে আপনাকে অবজেক্টগুলি পুনর্গঠন করতে হবে ।Foo
foo
X
মডিউল না হয় তবে আপনি পারেনimport sys; reload(sys.modules[X.__module__])
is_changed
ফাংশনটি কেবল একটি স্বেচ্ছাসেবী ফাংশন যা আপনাকে লিখতে হবে; এটি কোনও অন্তর্নির্মিত নয়। উদাহরণস্বরূপ, এটি সম্ভবত আপনি যে মডিউলটি আমদানি করছেন তার সাথে সম্পর্কিত ফাইলটি খুলতে পারে এবং এটি পরিবর্তিত হয়েছে কিনা তা দেখার জন্য এটি ক্যাশেড সংস্করণ দিয়ে আলাদা করতে পারে।
পাইথন –.০-৩.৩ এ আপনি ব্যবহার করবেন: imp.reload(module)
তবে, (ধন্যবাদ @ স্টেফান! ) এর imp
পক্ষে, 3.4 importlib
এ অবমূল্যায়ন করা হয়েছিল ।
আমি মনে করি , অতএব, আপনি এখন ব্যবহার করবেন importlib.reload(module)
, যদিও আমি নিশ্চিত নই।
reload(__builtins__)
2.x
কোনও মডিউল খাঁটি পাইথন না হলে মুছতে মুছতে বিশেষত অসুবিধা হতে পারে।
এখান থেকে কিছু তথ্য দেওয়া হল: আমি কীভাবে সত্যিই আমদানি করা মডিউলটি মুছব?
রেফারেন্সের আসল সংখ্যাটি জানতে আপনি 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 () ফাংশনের একটি নিদর্শন।
setattr(package, "empty", None)
reload()
কেবলমাত্র সর্বাধিক সর্বাধিক মডিউলটি পুনরায় লোড করে এবং এর অভ্যন্তরীণ কিছু পুনরায় লোড হবে না যতক্ষণ না আপনি প্রথমে এটি sys.modules থেকে মুছুন।
reload(module)
, তবে কেবল যদি এটি সম্পূর্ণ একা থাকে। যদি মডিউলে অন্য কোনও কিছুর রেফারেন্স থাকে (বা মডিউলের সাথে সম্পর্কিত কোনও বস্তু), তবে আপনি পুরানো কোডটি আপনার প্রত্যাশার চেয়ে বেশি সময় ধরে ঝুলিয়ে রাখার কারণে সূক্ষ্ম এবং কৌতূহলীয় ত্রুটি পাবেন এবং isinstance
বিভিন্ন সংস্করণে কাজ না করার মতো জিনিসগুলি একই কোড
আপনার যদি একমুখী নির্ভরতা থাকে তবে পুরানো কোডের সমস্ত রেফারেন্স থেকে মুক্তি পেতে আপনাকে পুনরায় লোড করা মডিউলটির উপর নির্ভর করে সমস্ত মডিউলও পুনরায় লোড করতে হবে। এবং তারপরে পুনরায় লোড মডিউলগুলি পুনরায় লোড করা মডিউলগুলির উপর নির্ভর করে, পুনরাবৃত্তভাবে।
আপনার যদি বিজ্ঞপ্তি নির্ভরতা থাকে, যা খুব সাধারণ হয় উদাহরণস্বরূপ আপনি যখন প্যাকেজটি পুনরায় লোড করার বিষয়ে আলোচনা করছেন, আপনাকে অবশ্যই গোষ্ঠীর সমস্ত মডিউলগুলি একসাথে আনলোড করতে হবে। আপনি reload()
এটি দিয়ে এটি করতে পারবেন না কারণ এটি প্রতিটি মডিউলটির নির্ভরতা সতেজ হওয়ার আগে পুনরায় আমদানি করবে, পুরনো রেফারেন্সগুলিকে নতুন মডিউলগুলিতে ক্রাইপ করার অনুমতি দেবে।
এক্ষেত্রে এটি করার একমাত্র উপায় হ্যাক করা sys.modules
যা একধরণের অসমর্থিত। আপনি sys.modules
পরবর্তী আমদানিতে পুনরায় লোড করতে চান এমন প্রতিটি এন্ট্রির মধ্য দিয়ে যেতে হবে এবং মুছে ফেলতে হবে, এবং None
ব্যর্থ আপেক্ষিক আমদানিতে ক্যাচ ব্যর্থ হওয়ার ক্ষেত্রে বাস্তবায়নের কোনও সমস্যা মোকাবেলা করার জন্য যার মান রয়েছে সেগুলিও মুছে ফেলতে হবে। এটি মারাত্মকভাবে সুন্দর নয় তবে যতক্ষণ আপনার সম্পূর্ণ নির্ভরশীলতার সেট রয়েছে যা এর কোডবেসের বাইরে রেফারেন্স রাখে না, এটি কার্যক্ষম।
সার্ভারটি পুনরায় চালু করা সম্ভবত সেরা। :-)
None
মানগুলির সাথে অংশটি বিশদভাবে বর্ণনা করতে পারেন কারণ আমি এই ইস্যুতে ঠিক চলেছি: আমি sys.modules
কিছু আমদানি করা নির্ভরতা হ'ল এবং পুনরায় আমদানির পরে আইটেমগুলি মুছছি None
।
None
'সত্যিকারের' এন্ট্রিগুলি মুছে ফেলা হলে কীভাবে এন্ট্রিগুলি আমদানি প্রক্রিয়াটির মধ্য দিয়ে ফিরে যেতে সক্ষম হয়েছিল এবং আমি এটি ২.7-এ ঘটতে পারি না বলে মনে করি; ভবিষ্যতে অবশ্যই এটি আর সমস্যা নয় কারণ অন্তর্নিহিত আপেক্ষিক আমদানি চলে গেছে। ইতিমধ্যে, None
মান সহ সমস্ত এন্ট্রি মুছে ফেলা এটি ঠিক করে দেবে বলে মনে হচ্ছে।
reload
ফাংশনটি বোঝাতে চাইছেন ? এটি অন্তর্নির্মিত, আপনাকে কোনও লাইব্রেরি আমদানি করতে হবে না।
if 'myModule' in sys.modules:
del sys.modules["myModule"]
nose.run()
পরেও রয়ে গেছেreload(my_module)
%run my_module
[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
।
import sys; import json; del sys.modules['json']; print(json.dumps([1]))
এবং জেসন মডিউলটি এখনও সিএস.মডিউলগুলিতে না থাকলেও এখনও কাজ করছে।
পাইথন 2 এর জন্য বিল্ট-ইন ফাংশন পুনরায় লোড () ব্যবহার করুন :
reload(module)
পাইথন 2 এবং 3.2–3.3 মডিউল ইমপ থেকে পুনরায় লোড ব্যবহার করুন :
import imp
imp.reload(module)
কিন্তু imp
অবচিত সংস্করণ 3.4 থেকে importlib পক্ষে , তাই ব্যবহার:
import importlib
importlib.reload(module)
অথবা
from importlib import reload
reload(module)
from six import reload_module
( pip install six
অবশ্যই প্রথম হওয়া প্রয়োজন )
from six.moves import reload_module
নিম্নলিখিত কোডটি আপনাকে পাইথন 2/3 সামঞ্জস্যের অনুমতি দেয়:
try:
reload
except NameError:
# Python 3
from imp import reload
আপনি এটি reload()
উভয় সংস্করণে যেমন ব্যবহার করতে পারেন যা জিনিসকে সহজ করে তোলে।
গৃহীত উত্তরটি এক্স আমদানি ওয়াই কেসটি পরিচালনা করে না। এই কোডটি এটি পরিচালনা করে এবং মানক আমদানির ক্ষেত্রেও:
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')
fromlist='*'
?
from
আমদানি বিবৃতিতে প্রায় সমস্ত ব্যবহার বন্ধ করতে প্রবণতা করছি । import <package>
কোডটিতে কেবল সম্পূর্ণ এবং স্পষ্টভাবে প্যাকেজ.সইম্বল। উপলব্ধি করুন এটি সর্বদা সম্ভব বা পছন্দসই নাও হতে পারে। (এখানে একটি ব্যতিক্রম এখানে: ভবিষ্যতে আমদানি মুদ্রণ_প্রণালী থেকে))
foo = reload(foo); from foo import *
এটি একটি মডিউল পুনরায় লোড করার আধুনিক উপায়:
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
।
from importlib import reload
। তাহলে আপনি করতে পারেন reload(MODULE_NAME)
। এই ফাংশন জন্য কোন প্রয়োজন নেই।
modulereload(MODULE_NAME)
চেয়ে বেশি স্ব-ব্যাখ্যাযোগ্য reload(MODULE_NAME)
এবং অন্যান্য ক্রিয়াকলাপের সাথে দ্বন্দ্ব নেওয়ার কম সুযোগ রয়েছে।
আপনি যদি কোনও সার্ভারে না থেকে থাকেন তবে বিকাশ করছেন এবং ঘন ঘন একটি মডিউল পুনরায় লোড করা প্রয়োজন, এখানে একটি সুন্দর টিপ।
প্রথমে নিশ্চিত করুন যে আপনি জুপিটার নোটবুক প্রকল্প থেকে দুর্দান্ত আইপিথন শেলটি ব্যবহার করছেন। Jupyter ইনস্টল করার পরে, আপনার সাথে শুরু করতে পারেন ipython
, অথবা jupyter console
, অথবা এমনকি ভাল,jupyter qtconsole
, আপনি যে কোনো OS এ কোড সমাপ্তির সঙ্গে একটা চমৎকার রঙী কনসোল দেব পারে।
এখন আপনার শেলের মধ্যে, টাইপ করুন:
%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.
আমার মতো যারা যারা সমস্ত মডিউলগুলি আনলোড করতে চান (যখন ইম্যাক্সের অধীনে পাইথন দোভাষীর মধ্যে চলছে ):
for mod in sys.modules.values():
reload(mod)
আরও তথ্য পাইথন মডিউলগুলি রিলোড করছে ।
sys.modules.values()
কিছুই মডিউল নয়। উদাহরণস্বরূপ: >>> টাইপ করুন (sys.modules.values () [1]) <ক্লাস 'ইমেল.লজি ইম্পোর্টার'> সুতরাং যদি আমি সেই কোডটি চালানোর চেষ্টা করি তবে এটি পড়ে যায় (আমি জানি এটি একটি ব্যবহারিক সমাধান হিসাবে বোঝানো হয়নি, শুধু যে নির্দেশ করে)।
if mod and mod.__name__ != "__main__": imp.reload(mod)
এনটহাউট ট্রেইটসের একটি মডিউল রয়েছে যা এটির জন্য মোটামুটি ভালভাবে কাজ করে। https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
এটি যে কোনও মডিউল পরিবর্তন করা হয়েছে তা পুনরায় লোড করবে এবং এটি ব্যবহার করে এমন অন্যান্য মডিউল এবং উদাহরণস্বরূপ বস্তু আপডেট করবে। এটি বেশিরভাগ সময় __very_private__
পদ্ধতিগুলির সাথে কাজ করে না , এবং শ্রেণীর উত্তরাধিকারকে দম বন্ধ করতে পারে তবে পাইক্ট গুইস লেখার সময় হোস্ট অ্যাপ্লিকেশনটি পুনরায় চালু করা বা মায়া বা নুকের মতো প্রোগ্রামের অভ্যন্তরে চালিত স্টাফ থেকে আমাকে পাগল পরিমাণ বাঁচায়। এটি সম্ভবত 20-30% সময় নিয়ে কাজ করে না তবে এটি এখনও অবিশ্বাস্যরূপে সহায়ক।
এনটহোটের প্যাকেজ ফাইলগুলি পরিবর্তনের মুহুর্তে পুনরায় লোড করে না - আপনাকে এটিকে স্পষ্টতই কল করতে হবে - তবে আপনার যদি সত্যিই এটির প্রয়োজন হয় তবে এটি কার্যকর করা এত কঠিন নয় should
যারা পাইথন 3 ব্যবহার করছেন এবং ইমপোর্টলিব থেকে পুনরায় লোড করেন।
আপনার যদি মনে হয় যে সমস্যাটি মনে হয় যে মডিউলটি পুনরায় লোড হচ্ছে না ... কারণ এটি পিআইসি পুনরায় সংযোগ করতে কিছুটা সময় প্রয়োজন (60 সেকেন্ড পর্যন্ত) I আমি এই ইঙ্গিতটি লিখছি যাতে আপনি জানেন যে আপনি এই জাতীয় সমস্যাটি অনুভব করেছেন কিনা।
2018-02-01
foo
অবশ্যই সাফল্যের সাথে আগে আমদানি করা উচিত। from importlib import reload
, reload(foo)
31.5। Importlib - আমদানির বাস্তবায়ন - পাইথন 3.6.4 ডকুমেন্টেশন
অন্য বিকল্প। দেখুন যে পাইথন ডিফল্ট importlib.reload
কেবল একটি আর্গুমেন্ট হিসাবে পাস করা লাইব্রেরিটিকে পুনরায় আমদানি করবে। এটি আপনার লাইব্রেরিগুলি আমদানি করে এমন লাইব্রেরিগুলি পুনরায় লোড করবে না । যদি আপনি প্রচুর ফাইল পরিবর্তন করেন এবং আমদানি করার জন্য কিছুটা জটিল প্যাকেজ থাকে তবে আপনাকে অবশ্যই একটি গভীর পুনরায় লোড করতে হবে ।
আপনার আইপিথন বা জুপিটার ইনস্টল করা থাকলে আপনি সমস্ত লিবস গভীরভাবে পুনরায় লোড করার জন্য একটি ফাংশন ব্যবহার করতে পারেন:
from IPython.lib.deepreload import reload as dreload
dreload(foo)
যদি আপনার কাছে জুপিটার না থাকে তবে আপনার শেলটিতে এই কমান্ডটি দিয়ে এটি ইনস্টল করুন:
pip3 install jupyter
reload() argument must be module
। আমি একটি কাস্টম ফাংশন আমদানি ব্যবহার করছি এবং এটি কাজ করবে বলে মনে হচ্ছে না। অন্তর্নির্মিত মডিউলগুলি ব্যবহার করে কাজ করে। :-( আমি আমার কোডে করা প্রতিটি ছোট্ট পরিবর্তনের জন্য আইপিথন পুনরায় লোড করা সময় নষ্ট করা ...
কেবলমাত্র পুনরায় সেট করার তথ্য পাওয়ার জন্য আগে থেকে সমাধানটি ভাল, তবে এটি সমস্ত রেফারেন্স পরিবর্তন করবে না ( reload
তবে তার চেয়ে কম তবে প্রয়োজনীয়)। প্রকৃতপক্ষে সমস্ত রেফারেন্স সেট করতে, আমাকে আবর্জনা সংগ্রাহকের ভিতরে যেতে হয়েছিল, এবং সেখানে উল্লেখগুলি আবার লিখতে হয়েছিল। এখন এটি একটি যাদুমন্ত্র মত কাজ করে!
মনে রাখবেন যে জিসিটি বন্ধ করা থাকলে, বা জিসি দ্বারা তদারকি না করা ডেটা পুনরায় লোড করা হলে এটি কাজ করবে না । আপনি যদি জিসির সাথে ঝামেলা করতে না চান তবে আসল উত্তরটি আপনার পক্ষে যথেষ্ট।
নতুন কোড:
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)
@ বোবিন্সের উত্তরে যেমন লেখা আছে, অন্য মডিউলে যদি ইতিমধ্যে সেই মডিউলটির কোনও রেফারেন্স থাকে (বিশেষত যদি এটি 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
দ্রষ্টব্য: যত্ন সহকারে ব্যবহার করুন! এগুলি পেরিফেরিয়াল মডিউলগুলিতে ব্যবহার করা (মডিউলগুলি যা বাহ্যিকভাবে ব্যবহৃত ক্লাসগুলি সংজ্ঞায়িত করে, উদাহরণস্বরূপ) পাইথনের অভ্যন্তরীণ সমস্যা হতে পারে (যেমন পিকিং / আন-পিকিং ইস্যু)।
আমার পক্ষে আবাকাসের ক্ষেত্রে এটি কাজ করে। আপনার ফাইলটি 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'])
সাব্লাইম টেক্সটের ভিতরে কিছু পুনরায় লোড করার চেষ্টা করতে গিয়ে আমি অনেক সমস্যার মুখোমুখি হয়েছি, তবে শেষ পর্যন্ত আমি মডিউলগুলি পুনরায় লোড করতে ব্যবহারের কোডের ভিত্তিতে সাবলাইম পাঠ্যে মডিউলগুলি পুনরায় লোড করতে এই ইউটিলিটিটি লিখতে পারি 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()
এটি পরীক্ষার ফাইলগুলি পুনরায় লোড করবে। সাব্লাইম টেক্সট ( Python 3.3.6
) এর মাধ্যমে এটি অনেক ঘটে কারণ এর দোভাষী কখনই বন্ধ হয় না (যদি না আপনি সাব্লাইম পাঠ্যটি পুনরায় আরম্ভ না করেন, অর্থাত্ Python3.3
দোভাষী)।
অন্য কোনও উপায় হতে পারে কোনও ফাংশনে মডিউলটি আমদানি করা। ফাংশনটি মডিউলটি সম্পূর্ণ করার পরে এইভাবে আবর্জনা সংগ্রহ করা যায়।
sys.modules
।