python 中怎么动态 import 模块? - V2EX
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 8245 次点击
    这是一个创建于 3547 天前的主题,其中的信息可能已经有所发展或是发生改变。
    需要根据不同的条件导入不同的模块该怎么做?
    现在用__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 _resolvename(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     Solana     2676 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 13:21 PVG 21:21 LAX 05:21 JFK 08:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86