আমি কীভাবে একটি মডিউল আনলোড (পুনরায় লোড) করব?


796

আমার দীর্ঘকাল ধরে চলছে পাইথন সার্ভার এবং সার্ভারটি পুনরায় চালু না করে কোনও পরিষেবা আপগ্রেড করতে সক্ষম হতে চাই। এটি করার সর্বোত্তম উপায় কী?

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

53
মেমো টিপ: "আমদানি" এর অর্থ "লোড" নয়, এর অর্থ "এখনও লোড না করা থাকলে লোড এবং তারপরে নেমস্পেসে আমদানি করুন"।
কোস

3
প্রশ্নটি 'আনলোড' অন্তর্ভুক্ত করা উচিত নয় কারণ পাইথনটিতে এটি এখনও সম্ভব নয় - নীচে উত্তর হিসাবে পুনরায় লোড করা একটি পরিচিত দৃষ্টান্ত
রবার্টমোগগাচ

পাই 2 এক্সি অ্যাপে ডায়নামিক মডিউল ব্যবহার করার সময় আমারও একই সমস্যা ছিল। পাইপেক্স যেমন সর্বদা জিপ ডিরেক্টরিতে বাইকোড রাখে পুনরায় লোড কাজ করে না। তবে আমি আমদানি-ফাইল ফাইল মডিউলটি ব্যবহার করে একটি কাজের সমাধান পেয়েছি। এখন আমার আবেদন ভাল কাজ করছে।
প্রীতম প্যান

2
আপনি কি যদি "আনলোড" করতে চান কারণ কোড দ্বারা একটি .pyc ফাইল মুছে ফেলার চেষ্টা করা হচ্ছে?
ডার্কগ্যাজে

উত্তর:


787

ইতিমধ্যে বিল্টিন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থাকলে আপনাকে অবজেক্টগুলি পুনর্গঠন করতে হবে ।Foofoo


10
আসলে, আপনি যখন কোনও ফাইল পরিবর্তন করেন তখন জাঙ্গো দেব সার্ভারটি পুনরায় চালু হয় .. (এটি সার্ভারটি পুনঃসূচনা করে, কেবলমাত্র মডিউলটি পুনরায় লোড করে না)
হ্যাসেন

25
এই "is_ চেঞ্জড" ফাংশনটি কোথা থেকে আসছে? আমি এটিতে কোনও নথিপত্র দেখতে পাচ্ছি না এবং এটি আমার পাইথন ৩.১.৩ পরিবেশে চলে না এবং এটি ২.6.৪-তেও চালায় না।
jedmao

5
কোন সিডিলারি নয়, জ্যাঙ্গো কেবল পুনরায় লোড ব্যবহার করতে পারে না: puneit.sourceforge.net/notes/reloading.html
রায়

14
@ বার্টোসকেপি যদি Xমডিউল না হয় তবে আপনি পারেনimport sys; reload(sys.modules[X.__module__])
ড্রেভিকো

5
@ জেদমাও @ জেমসড্রেপার আমি পুরোপুরি নিশ্চিত যে is_changedফাংশনটি কেবল একটি স্বেচ্ছাসেবী ফাংশন যা আপনাকে লিখতে হবে; এটি কোনও অন্তর্নির্মিত নয়। উদাহরণস্বরূপ, এটি সম্ভবত আপনি যে মডিউলটি আমদানি করছেন তার সাথে সম্পর্কিত ফাইলটি খুলতে পারে এবং এটি পরিবর্তিত হয়েছে কিনা তা দেখার জন্য এটি ক্যাশেড সংস্করণ দিয়ে আলাদা করতে পারে।
জেমস মাছুগ

252

পাইথন –.০-৩.৩ এ আপনি ব্যবহার করবেন: imp.reload(module)

BDFL করেছে উত্তরে এই প্রশ্ন।

তবে, (ধন্যবাদ @ স্টেফান! ) এর impপক্ষে, 3.4 importlibএ অবমূল্যায়ন করা হয়েছিল

আমি মনে করি , অতএব, আপনি এখন ব্যবহার করবেন importlib.reload(module), যদিও আমি নিশ্চিত নই।


23
আন্তরিক নবাগত পাইথন 2 এবং 3 এর মধ্যে সমালোচনামূলক সূক্ষ্মতা সম্পর্কে জানতে কৃতজ্ঞ
স্মান্ডোলি

24
ইমপ্রেড (ইমপ) বৈধ?
Loïc Faure-Lacroix

2
@ LoïcFaure-Lacroix একইভাবে reload(__builtins__)2.x
জেবার্নার্ডো

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
সেই দৃশ্যের জন্য বিশেষভাবে ড্রেডলোড নয়?
জোশ

@ জোশ: না, এটি কোনও প্যাকেজ ট্রি পুনরায় লোড করার জন্য এবং তবুও এটি কেবল ততক্ষণ কাজ করবে যতক্ষণ প্যাকেজের বাইরে / বৃত্তাকার নির্ভরতা নেই।
ববিনস

1
আপনি কি Noneমানগুলির সাথে অংশটি বিশদভাবে বর্ণনা করতে পারেন কারণ আমি এই ইস্যুতে ঠিক চলেছি: আমি sys.modulesকিছু আমদানি করা নির্ভরতা হ'ল এবং পুনরায় আমদানির পরে আইটেমগুলি মুছছি None
স্ক্লামার

@shclamar: দেখুন stackoverflow.com/questions/1958417/... (এবং সেখান থেকে সংযোগগুলি) পটভূমির জন্য। এটি আমার কাছে অস্পষ্ট (এমনকি আমদানি কোড কোডটি দেখেও) None'সত্যিকারের' এন্ট্রিগুলি মুছে ফেলা হলে কীভাবে এন্ট্রিগুলি আমদানি প্রক্রিয়াটির মধ্য দিয়ে ফিরে যেতে সক্ষম হয়েছিল এবং আমি এটি ২.7-এ ঘটতে পারি না বলে মনে করি; ভবিষ্যতে অবশ্যই এটি আর সমস্যা নয় কারণ অন্তর্নিহিত আপেক্ষিক আমদানি চলে গেছে। ইতিমধ্যে, Noneমান সহ সমস্ত এন্ট্রি মুছে ফেলা এটি ঠিক করে দেবে বলে মনে হচ্ছে।
ববিনস ২

1
@ এলিথেসইয়ান: আপনি কি 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.')]
ড্রিভিকো

আমি মনে করি না যে মডিউলটি আনলোড করে। পাইথন ৩.৮-তে: import sys; import json; del sys.modules['json']; print(json.dumps([1]))এবং জেসন মডিউলটি এখনও সিএস.মডিউলগুলিতে না থাকলেও এখনও কাজ করছে।
সেপম্যান

60

পাইথন 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)

2
এগুলির যে কোনও একটি কেস পরিচালনা করতে: from six import reload_module( pip install sixঅবশ্যই প্রথম হওয়া প্রয়োজন )
এ্যান্ট্রপিক

@ অ্যান্ট্রোপিক: ছয়টি প্যাকেজ ব্যবহার করার পরামর্শ দেওয়া ভাল পরামর্শ, তবে বাক্য from six.moves import reload_module
গঠনটি

23

নিম্নলিখিত কোডটি আপনাকে পাইথন 2/3 সামঞ্জস্যের অনুমতি দেয়:

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

আপনি এটি reload()উভয় সংস্করণে যেমন ব্যবহার করতে পারেন যা জিনিসকে সহজ করে তোলে।


18

গৃহীত উত্তরটি এক্স আমদানি ওয়াই কেসটি পরিচালনা করে না। এই কোডটি এটি পরিচালনা করে এবং মানক আমদানির ক্ষেত্রেও:

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 *
রায়পুন

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)এবং অন্যান্য ক্রিয়াকলাপের সাথে দ্বন্দ্ব নেওয়ার কম সুযোগ রয়েছে।
রিচি বেনডাল

@ রিচিবেনডল দুঃখিত, তবে এই উত্তরটি সম্পূর্ণ ভুল। পুনরায় লোড () ফাংশনটি মডিউলটির নাম নেয়, মডিউল নাম নয় ... ডকসগুলি পড়ুন: ডকস.পিথন.আর / 3 / লাইব্রেরি / আইপোর্টলিব.হ.টি.এম.এল. ।
mbdevpl

আমি আপনার মতামত প্রতিফলিত করতে আমার উত্তর পরিবর্তন করেছি।
রিচি বেন্ডল

13

আপনি যদি কোনও সার্ভারে না থেকে থাকেন তবে বিকাশ করছেন এবং ঘন ঘন একটি মডিউল পুনরায় লোড করা প্রয়োজন, এখানে একটি সুন্দর টিপ।

প্রথমে নিশ্চিত করুন যে আপনি জুপিটার নোটবুক প্রকল্প থেকে দুর্দান্ত আইপিথন শেলটি ব্যবহার করছেন। 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.

7

আমার মতো যারা যারা সমস্ত মডিউলগুলি আনলোড করতে চান (যখন ইম্যাক্সের অধীনে পাইথন দোভাষীর মধ্যে চলছে ):

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

আরও তথ্য পাইথন মডিউলগুলি রিলোড করছে


আসলে এটি নির্ভরযোগ্যভাবে কাজ করে না বলে মনে হয় (২.6-এ) কারণ সমস্ত sys.modules.values()কিছুই মডিউল নয়। উদাহরণস্বরূপ: >>> টাইপ করুন (sys.modules.values ​​() [1]) <ক্লাস 'ইমেল.লজি ইম্পোর্টার'> সুতরাং যদি আমি সেই কোডটি চালানোর চেষ্টা করি তবে এটি পড়ে যায় (আমি জানি এটি একটি ব্যবহারিক সমাধান হিসাবে বোঝানো হয়নি, শুধু যে নির্দেশ করে)।
ফ্রান্সিস ডেভে

এটি পূর্বের অজগরগুলিতেও কাজ করে না - যেমন লেখা আছে। আমাকে কিছু নাম বাদ দিতে হয়েছিল। আমি যখন এই কোডটি আমার নতুন কম্পিউটারে নিয়ে যাই তখন আমি পোস্টটি আপডেট করব।

2
কিছু পরিবর্তনের পরে পাইথন ২.7 এ দুর্দান্ত কাজ করে:if mod and mod.__name__ != "__main__": imp.reload(mod)
জজারেক টমকজাক

2
এটি আমার পক্ষে ভাল কাজ করে: আমদানি ইমম্প [পুনরায় লোড (এম) এর জন্য সিস.মডিউলস.ভালিউস () যদি এম এবং এম " " নাম না হয় .__ নাম এবং ইমপি। বিল্টিন (এম .__ নাম__)] না
প্যাট্রিক ওল্ফ

5

এনটহাউট ট্রেইটসের একটি মডিউল রয়েছে যা এটির জন্য মোটামুটি ভালভাবে কাজ করে। https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

এটি যে কোনও মডিউল পরিবর্তন করা হয়েছে তা পুনরায় লোড করবে এবং এটি ব্যবহার করে এমন অন্যান্য মডিউল এবং উদাহরণস্বরূপ বস্তু আপডেট করবে। এটি বেশিরভাগ সময় __very_private__পদ্ধতিগুলির সাথে কাজ করে না , এবং শ্রেণীর উত্তরাধিকারকে দম বন্ধ করতে পারে তবে পাইক্ট গুইস লেখার সময় হোস্ট অ্যাপ্লিকেশনটি পুনরায় চালু করা বা মায়া বা নুকের মতো প্রোগ্রামের অভ্যন্তরে চালিত স্টাফ থেকে আমাকে পাগল পরিমাণ বাঁচায়। এটি সম্ভবত 20-30% সময় নিয়ে কাজ করে না তবে এটি এখনও অবিশ্বাস্যরূপে সহায়ক।

এনটহোটের প্যাকেজ ফাইলগুলি পরিবর্তনের মুহুর্তে পুনরায় লোড করে না - আপনাকে এটিকে স্পষ্টতই কল করতে হবে - তবে আপনার যদি সত্যিই এটির প্রয়োজন হয় তবে এটি কার্যকর করা এত কঠিন নয় should


5

যারা পাইথন 3 ব্যবহার করছেন এবং ইমপোর্টলিব থেকে পুনরায় লোড করেন।

আপনার যদি মনে হয় যে সমস্যাটি মনে হয় যে মডিউলটি পুনরায় লোড হচ্ছে না ... কারণ এটি পিআইসি পুনরায় সংযোগ করতে কিছুটা সময় প্রয়োজন (60 সেকেন্ড পর্যন্ত) I আমি এই ইঙ্গিতটি লিখছি যাতে আপনি জানেন যে আপনি এই জাতীয় সমস্যাটি অনুভব করেছেন কিনা।



3

অন্য বিকল্প। দেখুন যে পাইথন ডিফল্ট importlib.reloadকেবল একটি আর্গুমেন্ট হিসাবে পাস করা লাইব্রেরিটিকে পুনরায় আমদানি করবে। এটি আপনার লাইব্রেরিগুলি আমদানি করে এমন লাইব্রেরিগুলি পুনরায় লোড করবে না । যদি আপনি প্রচুর ফাইল পরিবর্তন করেন এবং আমদানি করার জন্য কিছুটা জটিল প্যাকেজ থাকে তবে আপনাকে অবশ্যই একটি গভীর পুনরায় লোড করতে হবে ।

আপনার আইপিথন বা জুপিটার ইনস্টল করা থাকলে আপনি সমস্ত লিবস গভীরভাবে পুনরায় লোড করার জন্য একটি ফাংশন ব্যবহার করতে পারেন:

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

যদি আপনার কাছে জুপিটার না থাকে তবে আপনার শেলটিতে এই কমান্ডটি দিয়ে এটি ইনস্টল করুন:

pip3 install jupyter

ইমপাইলিব থেকে এই আইপিথন ড্রেলোড এবং পুনরায় লোড উভয়ই অভিযোগ করে reload() argument must be module। আমি একটি কাস্টম ফাংশন আমদানি ব্যবহার করছি এবং এটি কাজ করবে বলে মনে হচ্ছে না। অন্তর্নির্মিত মডিউলগুলি ব্যবহার করে কাজ করে। :-( আমি আমার কোডে করা প্রতিটি ছোট্ট পরিবর্তনের জন্য আইপিথন পুনরায় লোড করা সময় নষ্ট করা ...
এম

2

সম্পাদনা করুন (উত্তর ভি 2)

কেবলমাত্র পুনরায় সেট করার তথ্য পাওয়ার জন্য আগে থেকে সমাধানটি ভাল, তবে এটি সমস্ত রেফারেন্স পরিবর্তন করবে না ( 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

দ্রষ্টব্য: যত্ন সহকারে ব্যবহার করুন! এগুলি পেরিফেরিয়াল মডিউলগুলিতে ব্যবহার করা (মডিউলগুলি যা বাহ্যিকভাবে ব্যবহৃত ক্লাসগুলি সংজ্ঞায়িত করে, উদাহরণস্বরূপ) পাইথনের অভ্যন্তরীণ সমস্যা হতে পারে (যেমন পিকিং / আন-পিকিং ইস্যু)।


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/…
সিহাহ

0

সাব্লাইম টেক্সটের ভিতরে কিছু পুনরায় লোড করার চেষ্টা করতে গিয়ে আমি অনেক সমস্যার মুখোমুখি হয়েছি, তবে শেষ পর্যন্ত আমি মডিউলগুলি পুনরায় লোড করতে ব্যবহারের কোডের ভিত্তিতে সাবলাইম পাঠ্যে মডিউলগুলি পুনরায় লোড করতে এই ইউটিলিটিটি লিখতে পারি 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দোভাষী)।


-1

অন্য কোনও উপায় হতে পারে কোনও ফাংশনে মডিউলটি আমদানি করা। ফাংশনটি মডিউলটি সম্পূর্ণ করার পরে এইভাবে আবর্জনা সংগ্রহ করা যায়।


4
মডিউলটি কখনই জঞ্জাল সংগ্রহ করবে না কারণ একটি বিশ্বব্যাপী রেফারেন্স অন্তত অন্তর্ভুক্ত রয়েছে sys.modules
সমস্ত কর্মী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.