গতিশীলভাবে আমদানি করা মডিউলটিতে কোনও শ্রেণীর স্ট্রিংয়ের নাম থেকে গতিশীল ইনস্ট্যান্টেশন?


179

পাইথনে, আমাকে কিছু শ্রেণি ইনস্ট্যান্ট করতে হবে, একটি স্ট্রিংয়ের নামটি জেনে তবে এই শ্রেণিটি গতিশীলভাবে আমদানি করা মডিউলে 'জীবনযাপন করে'। একটি উদাহরণ অনুসরণ করে:

লোডার-শ্রেণীর স্ক্রিপ্ট:

import sys
class loader:
  def __init__(self, module_name, class_name): # both args are strings
    try:
      __import__(module_name)
      modul = sys.modules[module_name]
      instance = modul.class_name() # obviously this doesn't works, here is my main problem!
    except ImportError:
       # manage import error

কিছু-গতিশীল-লোডড-মডিউল স্ক্রিপ্ট:

class myName:
  # etc...

আমি এই বিন্যাসটি লোড-শ্রেণীর দ্বারা ডিন-লোডড-মডিউলগুলিতে নির্দিষ্ট পূর্বনির্ধারিত আচরণ অনুসরণ করে যে কোনও গতিশীল-লোডড-মডিউল তৈরি করতে ব্যবহার করি ...

উত্তর:


249

আপনি getattr ব্যবহার করতে পারেন

getattr(module, class_name)

ক্লাস অ্যাক্সেস করতে। আরও সম্পূর্ণ কোড:

module = __import__(module_name)
class_ = getattr(module, class_name)
instance = class_()

নীচে উল্লিখিত হিসাবে , আমরা Importlib ব্যবহার করতে পারি

import importlib
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
instance = class_()

3
module = __import__(module, fromlist=[name])শুধু আমার জন্য কাজ।
আম্পিরস্কি

16
উপরের উল্লিখিত স্মিভেন আমদানি পদ্ধতিতে যদি কারও সমস্যা হয় তবে আমি আমার কোডটি Importlib.import_module এর পরিবর্তে নিম্নলিখিত পদ্ধতিটি ব্যবহার করে আরও ভালভাবে কাজ করতে দেখেছি । যেমন ব্যবহার করা যায়: মডিউল = Importlib.import_module (মডিউল_নাম)
jpennell

@ জেপেনেল আপনার এই পোস্টটি পোস্ট করা উচিত যে উত্তর হিসাবে, প্রায়শই ফিরে আসা স্ট্রিংটি সরাসরি ব্যবহার করতে সক্ষম হওয়া আরও বেশি কার্যকরobj.__module__
অ্যান্ট্রপিক

importlib.import_moduleপ্রয়োজনে .py ফাইলটিকে একটি পাইপিতে লোড করার পাশাপাশি সম্পূর্ণ মডিউল.নেম.প্যাথিং.টো.সেট.টো. ক্লাস পরিচালনা করবে। __import__জ্যাঙ্গো পরিবেশে (এইটির বাইরে পরীক্ষা করা হয় না) এই জিনিসগুলির কোনওটিই করবে না
জেমস

122

TL; ড

এর সাথে রুট মডিউলটি আমদানি করুন importlib.import_moduleএবং getattrফাংশন ব্যবহার করে ক্লাসটির নাম দিয়ে লোড করুন :

# Standard import
import importlib
# Load "module.submodule.MyClass"
MyClass = getattr(importlib.import_module("module.submodule"), "MyClass")
# Instantiate the class (pass arguments to the constructor, if needed)
instance = MyClass()

ব্যাখ্যা

আপনি সম্ভবত __import__নামে হিসাবে একটি মডিউল গতিশীলভাবে আমদানি করতে ব্যবহার করতে চান না , কারণ এটি আপনাকে সাবমডিউলগুলি আমদানি করার অনুমতি দেয় না:

>>> mod = __import__("os.path")
>>> mod.join
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'join'

পাইথন ডকটি এখানে যা বলেছেন __import__:

দ্রষ্টব্য: এটি একটি উন্নত ফাংশন যা রোজকার পাইথন প্রোগ্রামিংয়ে প্রয়োজন হয় না, Importlib.import_module () এর বিপরীতে।

পরিবর্তে, importlibনাম দ্বারা একটি মডিউল গতিশীলভাবে আমদানি করতে স্ট্যান্ডার্ড মডিউলটি ব্যবহার করুন । এর মাধ্যমে getattrআপনি তার নামে কোনও শ্রেণি ইনস্ট্যান্ট করতে পারেন:

import importlib
my_module = importlib.import_module("module.submodule")
MyClass = getattr(my_module, "MyClass")
instance = MyClass()

আপনি আরও লিখতে পারেন:

import importlib
module_name, class_name = "module.submodule.MyClass".rsplit(".", 1)
MyClass = getattr(importlib.import_module(module_name), class_name)
instance = MyClass()

এই কোডটি পাইথনকে বৈধ ≥ 2.7 (পাইথন 3 সহ)।


1
হতে পারে আমি আপনার উত্তরটি বুঝতে পারি না, তবে আমি সাবমডিউলগুলি আমদানি করতে আমদানিটি ব্যবহার করেছি : __মম্পট __ ("মডিউল" "+ উপ-মডেল_নাম_স্ট্রিং)
জাভিয়ের নোভা সি।

নিম্নলিখিত কোডের একটি অ্যাট্রিবিউটআরারের ফলাফল: mod = __import__("os.path"); mod.joinযখন নিম্নলিখিতটি না করে:mod = importlib.import_module("os.path"); mod.join
রেগিস বি

ওহ, আমি দেখতে পেয়েছি, আপনি ঠিক বলেছেন তবে os.path.join পদ্ধতিটি পাওয়ার জন্য আমি নিম্নলিখিতগুলি করেছি: গেটআটার (sys.modules ["os.path"], "যোগদান")
জাভিয়ের নোভা সি।

হা! এবং আমি দেখতে পাচ্ছি যে এটি ব্যবহার করার পরে, ' আমদানি ' অপ্রয়োজনীয় এক্সডি
জাভিয়ের নভোয়া সি

2
উত্তর হিসাবে চিহ্নিত বিকল্পটি আমার পক্ষে কাজ করেনি (সাবমডিউলগুলি ব্যবহার করে) তবে এই উত্তরটি দেয়। আমি মনে করি এটি উত্তর হওয়া উচিত যেহেতু এটি গতিশীলভাবে মডিউল লোড করার জন্য আরও সাধারণ সমাধান।
rkachach

14

getattrএকটি স্ট্রিং থেকে একটি নাম থেকে একটি বৈশিষ্ট্য পেতে ব্যবহার করুন । অন্য কথায়, উদাহরণটি পান

instance = getattr(modul, class_name)()

10

কপি-পেস্ট স্নিপেট:

import importlib
def str_to_class(module_name, class_name):
    """Return a class instance from a string reference"""
    try:
        module_ = importlib.import_module(module_name)
        try:
            class_ = getattr(module_, class_name)()
        except AttributeError:
            logging.error('Class does not exist')
    except ImportError:
        logging.error('Module does not exist')
    return class_ or None

5

আপনি যদি এই বাক্যটি from foo.bar import foo2গতিশীলভাবে লোড করতে চান তবে আপনার এটি করা উচিত

foo = __import__("foo")
bar = getattr(foo,"bar")
foo2 = getattr(bar,"foo2")

instance = foo2()

4

একটি সহজভাবে pydoc.locateফাংশন ব্যবহার করতে পারেন ।

from pydoc import locate
my_class = locate("module.submodule.myclass")
instance = my_class()

2

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

def get_class(fully_qualified_path, module_name, class_name, *instantiation):
    """
    Returns an instantiated class for the given string descriptors
    :param fully_qualified_path: The path to the module eg("Utilities.Printer")
    :param module_name: The module name eg("Printer")
    :param class_name: The class name eg("ScreenPrinter")
    :param instantiation: Any fields required to instantiate the class
    :return: An instance of the class
    """
    p = __import__(fully_qualified_path)
    m = getattr(p, module_name)
    c = getattr(m, class_name)
    instance = c(*instantiation)
    return instance
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.