V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
dsp2138
V2EX  ›  Python

python 中怎么动态 import 模块?

  •  
  •   dsp2138 · Mar 14, 2016 · 8428 views
    This topic created in 3697 days ago, the information mentioned may be changed or developed.
    需要根据不同的条件导入不同的模块该怎么做?
    现在用__import__()可以导入,但怎么导入某个包下的模块
    A 文件夹下 fun.py需要导入子目录 A1 中的 a.py,b,py,c.py 其中 a.py 有 class Auser,b.py 中有 class Buser,c.py 中有 class Cuser,
    用 if 判断不同的条件导入分别导入 a.py,b.py.c.py
    我怎么该怎么做?

    谢谢
    我这里是 python3.4
    27 replies    2016-03-16 00:21:59 +08:00
    fy
        1
    fy  
       Mar 14, 2016
    楼主你问之前不妨先试一下:

    if True: import re
    else: import json

    In [51]: re
    Out[51]: <module 're' from 'd:\\python34\\lib\\re.py'>

    In [52]: json
    ---------------------------------------------------------------------------
    NameError Traceback (most recent call last)
    <ipython-input-52-832ed6b85533> in <module>()
    ----> 1 json

    NameError: name 'json' is not defined
    ericls
        2
    ericls  
       Mar 14, 2016
    if a:
    import A
    if b:
    import B
    if c:
    import C
    gx
        3
    gx  
       Mar 14, 2016
    看一下 import_module 实现,当然, 3.x 直接用了。

    """Backport of importlib.import_module from 3.x."""
    # While not critical (and in no way guaranteed!), it would be nice to keep this
    # code compatible with Python 2.3.
    import sys

    def _resolve_name(name, package, level):
    """Return the absolute name of the module to be imported."""
    if not hasattr(package, 'rindex'):
    raise ValueError("'package' not set to a string")
    dot = len(package)
    for x in xrange(level, 1, -1):
    try:
    dot = package.rindex('.', 0, dot)
    except ValueError:
    raise ValueError("attempted relative import beyond top-level "
    "package")
    return "%s.%s" % (package[:dot], name)


    def import_module(name, package=None):
    """Import a module.

    The 'package' argument is required when performing a relative import. It
    specifies the package to use as the anchor point from which to resolve the
    relative import to an absolute import.

    """
    if name.startswith('.'):
    if not package:
    raise TypeError("relative imports require the 'package' argument")
    level = 0
    for character in name:
    if character != '.':
    break
    level += 1
    name = _resolve_name(name[level:], package, level)
    __import__(name)
    return sys.modules[name]
    gx
        4
    gx  
       Mar 14, 2016
    2.x 的朋友移步 /PATH_TO_YOUR_PYTHON_LIB_FOLDER/importlib/__init__.py
    restran
        5
    restran  
       Mar 14, 2016
    还可以根据字符串动态导入包

    ```py
    def import_string(dotted_path):
    """
    Import a dotted module path and return the attribute/class designated by the
    last name in the path. Raise ImportError if the import failed.
    """
    try:
    module_path, class_name = dotted_path.rsplit('.', 1)
    except ValueError:
    msg = "%s doesn't look like a module path" % dotted_path
    raise ImportError(msg)

    module = import_module(module_path)

    try:
    return getattr(module, class_name)
    except AttributeError:
    msg = 'Module "%s" does not define a "%s" attribute/class' % (
    module_path, class_name)
    raise ImportError(msg)
    ```

    使用方法

    `import_string('a.b.c')`
    knightdf
        6
    knightdf  
       Mar 14, 2016
    if else.....
    import 几乎可以写在任何位置。。。写函数里也行,用的时候再 import
    jimzhong
        7
    jimzhong  
       Mar 14, 2016
    import 本来就是动态的哦
    Anthony117
        8
    Anthony117  
       Mar 14, 2016
    mengzhuo
        9
    mengzhuo  
       Mar 14, 2016 via iPhone
    标题党… ifelse 这叫动态 import ?
    我还以为说的是生成动态 class 和模块呢……
    我实现过这个,很好玩,感兴趣的同学可以联系我
    ksc010
        10
    ksc010  
       Mar 14, 2016
    应该是根据变量来导入不同的模块

    原来也遇到这样的问题,需要实现一个插件机制
    解决的办法有点笨: 现在一个目录(plugs/)的__init__.py 导入所有的需要的插件模块
    然后 在里面定义一个 函数 下面是简化代码

    def getPlug(plugname):
    glb=globals()

    return glb[plugname]

    其它地方要引用的话
    直接
    from plugs import getPlug

    plug=getPlug('plugA')
    ksc010
        11
    ksc010  
       Mar 14, 2016
    @ksc010 这个仅仅是在调用层看着比较“优雅”
    实际上还是把所有的模块预先导入进来了
    thinker3
        12
    thinker3  
       Mar 14, 2016
    @mengzhuo 你是说会写程序的程序?
    nevin47
        13
    nevin47  
       Mar 14, 2016
    我在猜 LZ 是不是想说在 ABC 文件都还不确定的情况下去 import ?

    我赞同 @restran 的方法,前几天做了一个自动适配的模块就用了这种方法,根据传参来动态 Import 模块
    leyle
        14
    leyle  
       Mar 14, 2016
    from importlib import import_module
    dsp2138
        15
    dsp2138  
    OP
       Mar 14, 2016
    @mengzhuo 请教,应该怎么做,或许我没有把需求说明白
    自定义的模块如果有数十个
    用 if else 这样当然可以导入,但这代码肯定是惨不忍睹!
    请教,该怎么做
    dsp2138
        16
    dsp2138  
    OP
       Mar 14, 2016
    @ksc010 考虑预先导入是不是会占用内存,所以想需要是导入用完回收!我这里理解可否对?
    mengzhuo
        18
    mengzhuo  
       Mar 14, 2016
    @thinker3
    是的呢,这才有意思嘛~
    代码、类啊、常量、函数啊都完全是按数据生成的,
    然而上层完全不知道,还是按传统方法 import 和使用~

    @dsp2138
    如果只是你这样需要时调用而已,那直接全部 import 也不是事。
    预先导入肯定占内存的,但是比起数据来说都是小菜一碟。
    thinker3
        19
    thinker3  
       Mar 14, 2016
    @mengzhuo 我发现我已经特别关注你了。
    loading
        20
    loading  
       Mar 14, 2016 via Android
    @dsp2138 一堆 if else 就感觉不优雅?你没写过复杂的的业务吧。
    ToughGuy
        21
    ToughGuy  
       Mar 14, 2016
    module = importlib.import_module('os.path')
    dsp2138
        22
    dsp2138  
    OP
       Mar 14, 2016
    @loading 本人纯业余选手,主业环境监测!基本没啥业务,何况负责复杂的业务逻辑呢
    gx
        23
    gx  
       Mar 14, 2016
    @mengzhuo meta class
    mengzhuo
        24
    mengzhuo  
       Mar 15, 2016 via iPhone
    @gx meta class 为什么叫 meta 有考虑过么?
    python 如此动态有趣的基础是什么?

    啊!我突然发现了我死的面试题哈哈啊
    gx
        25
    gx  
       Mar 15, 2016
    @mengzhuo

    Creating classes dynamically., no magic

    FooClass = type('FooClass', (), {})
    mengzhuo
        26
    mengzhuo  
       Mar 15, 2016
    @gx
    对于懂的人是没啥牛 B 的,
    关键是这种代码由数据驱动、啥都是 object 的思想
    还有 python 解析器是怎么 import 模块的, global()怎么注入,
    面试中级程序算是还行的题目了
    ╮(╯▽╰)╭
    gx
        27
    gx  
       Mar 16, 2016
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   992 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 22:17 · PVG 06:17 · LAX 15:17 · JFK 18:17
    ♥ Do have faith in what you're doing.