V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
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 · 2016-03-14 00:32:12 +08:00 · 7789 次点击
    这是一个创建于 3178 天前的主题,其中的信息可能已经有所发展或是发生改变。
    需要根据不同的条件导入不同的模块该怎么做?
    现在用__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 条回复    2016-03-16 00:21:59 +08:00
    fy
        1
    fy  
       2016-03-14 02:03:16 +08:00
    楼主你问之前不妨先试一下:

    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  
       2016-03-14 02:17:21 +08:00
    if a:
    import A
    if b:
    import B
    if c:
    import C
    gx
        3
    gx  
       2016-03-14 03:15:07 +08:00
    看一下 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  
       2016-03-14 03:18:20 +08:00
    2.x 的朋友移步 /PATH_TO_YOUR_PYTHON_LIB_FOLDER/importlib/__init__.py
    restran
        5
    restran  
       2016-03-14 08:46:47 +08:00
    还可以根据字符串动态导入包

    ```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  
       2016-03-14 08:52:29 +08:00
    if else.....
    import 几乎可以写在任何位置。。。写函数里也行,用的时候再 import
    jimzhong
        7
    jimzhong  
       2016-03-14 08:54:13 +08:00
    import 本来就是动态的哦
    Anthony117
        8
    Anthony117  
       2016-03-14 08:57:30 +08:00
    mengzhuo
        9
    mengzhuo  
       2016-03-14 09:16:26 +08:00 via iPhone
    标题党… ifelse 这叫动态 import ?
    我还以为说的是生成动态 class 和模块呢……
    我实现过这个,很好玩,感兴趣的同学可以联系我
    ksc010
        10
    ksc010  
       2016-03-14 09:23:22 +08:00
    应该是根据变量来导入不同的模块

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

    def getPlug(plugname):
    glb=globals()

    return glb[plugname]

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

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

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

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

    啊!我突然发现了我死的面试题哈哈啊
    gx
        25
    gx  
       2016-03-15 16:28:22 +08:00
    @mengzhuo

    Creating classes dynamically., no magic

    FooClass = type('FooClass', (), {})
    mengzhuo
        26
    mengzhuo  
       2016-03-15 18:07:02 +08:00
    @gx
    对于懂的人是没啥牛 B 的,
    关键是这种代码由数据驱动、啥都是 object 的思想
    还有 python 解析器是怎么 import 模块的, global()怎么注入,
    面试中级程序算是还行的题目了
    ╮(╯▽╰)╭
    gx
        27
    gx  
       2016-03-16 00:21:59 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1066 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:19 · PVG 07:19 · LAX 15:19 · JFK 18:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.