[Python] python带模块里延迟导入名字 →→→→→进入此内容的聊天室

来自 , 2020-10-10, 写在 Python, 查看 114 次.
URL http://www.code666.cn/view/5d0d5594
  1. #!/usr/bin/env python
  2. # -*-coding: utf8-*-
  3. # Title: lazynames.py
  4. # Author: Gribouillis for the python forum at www.daniweb.com
  5. # Created: 2012-09-25 12:20:15.556784 (isoformat date)
  6. # License: Public Domain
  7. # Use this code freely.
  8. """ module: lazynames -
  9.    Usage:
  10.        This module allows a python module to import symbols lazily
  11.        by declaring a "name getter function" like module A below:
  12.            
  13.            # module A
  14.            import lazynames
  15.            @lazynames.set_getter(__name__):
  16.            def func(module, attribute):
  17.                return attribute.upper()
  18.        
  19.        The client module B below imports symbols from A which
  20.        are not defined in A
  21.        
  22.            # module B
  23.            from A import foo, bar, baz
  24.            print(foo, bar, baz) # prints FOO BAR BAZ
  25.            
  26.        When foo, bar, baz are imported, module A uses its
  27.        "name getter function" to create values for these names.
  28.        Optionaly, the values can be stored in module A, so that
  29.        they would be created only once:
  30.            
  31.            @lazynames.set_getter(__name__)
  32.            def func(module, attribute):
  33.                value = attribute.upper()
  34.                setattr(module, attribute, value)
  35.                return value
  36.        
  37.        The following operations are possible:
  38.            
  39.            lazynames.set_getter("my.mod")(func)
  40.                Sets a name getter function for the module named "my.mod".
  41.                Module my.mod must already exist in sys.modules for this
  42.                to work.
  43.                This can be used more than once for the same module.
  44.                lazynames.set_getter("my.mod") can also be used as a
  45.                function decorator as shown above.
  46.                The "name getter function" can be called __getattr__ as
  47.                it behaves like a __getattr__ function: an expression
  48.                like my.mod.foo calls the name getter function with
  49.                argument "foo" if the name "foo" does not already exist
  50.                in module my.mod. The name getter function should raise
  51.                AttributeError to indicate that it can not create a value
  52.                for a given name.
  53.                By default, set_getter won't set a name getter for the
  54.                __main__ module, unless a special flag is passed:
  55.                    lazynames.set_getter("__main__", allow_main = True)(func)
  56.                This means that if the example module A above is used
  57.                as a script instead of being imported, the name getter
  58.                won't be set.
  59.            
  60.            lazynames.get_getter("my.mod")
  61.                returns the current name getter function of module my.mod
  62.                if it has been defined, otherwise return None
  63. """
  64. from collections import namedtuple
  65. from functools import partial
  66. import sys
  67. all = ["get_getter", "set_getter", "LazyModule"]
  68. Record = namedtuple("Record", "module getter")
  69. REGISTERED = dict()
  70. class LazyModule(object):
  71.     def __init__(self, dict):
  72.         self.__dict__ = dict
  73.        
  74.     def __getattr__(self, attr):
  75.         record = REGISTERED[self.__name__]
  76.         try:
  77.             return getattr(record.module, attr)
  78.         except AttributeError:
  79.             if attr.startswith("__"):
  80.                 raise
  81.             else:
  82.                 return record.getter(self, attr)
  83. def get_getter(name):
  84.     return REGISTERED[name].getter if name in REGISTERED else None
  85. def set_getter(name, allow_main = False):
  86.     return partial(_register, name = name, allow_main = allow_main)
  87. def _register(getter_func, name = "__main__", allow_main = False):
  88.     if getter_func is None:
  89.         _unregister(name)
  90.     elif allow_main or name != "__main__":
  91.         mod = (REGISTERED[name].module if name in REGISTERED
  92.                 else sys.modules[name])
  93.         record = Record(module = mod, getter = getter_func)
  94.         REGISTERED[name] = record
  95.         sys.modules[name] = LazyModule(mod.__dict__)
  96.     return getter_func
  97. def _unregister(name):
  98.     try:
  99.         record = REGISTERED.pop(name)
  100.     except KeyError:
  101.         pass
  102.     else:
  103.         sys.modules[name] = record.module
  104. #//python/5180

回复 "python带模块里延迟导入名字"

这儿你可以回复上面这条便签

captcha