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
yucongo
V2EX  ›  Python

怎么写才可以不用 exec?

  •  
  •   yucongo · 2017-07-09 21:11:39 +08:00 · 4401 次点击
    这是一个创建于 2713 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一段源码

    import importlib
    
    packages = ['pathlib', 'sys']
    modules = ['Path', 'path']
    
    for idx, package in enumerate(packages):
        tmp = importlib.import_module(package)
        importlib.reload(tmp)
        execline = modules[idx] + ' = getattr(tmp, "' + modules[idx] + '")'
        print(execline)
        exec(execline)
        # importlib.import_module('pathlib'); importlib.reload(pathlib); Path = getattr(pathlib, 'Path')
        # import pathlib; importlib.reload(pathlib); from pathlib import Path
    

    请问各路高人,有什么办法能替代上面的 exec

    稍微解释一下。exec 那句的功能是要动态载入数个我自己的函数…… 不过我用了系统的包做例子。非动态下 2 行 # 行其中的任一行都可以实现 exec行的功能。

    之所以不想用 exec 一是因为 pylint 出警告信息,二是因为 execline 这种写法太丑也容易出错。

    18 条回复    2017-07-10 19:51:27 +08:00
    264768502
        1
    264768502  
       2017-07-09 21:27:42 +08:00 via Android
    用 locals?
    yucongo
        2
    yucongo  
    OP
       2017-07-09 21:34:37 +08:00
    @264768502 大侠可不可以说仔细一点,感谢。

    eval(...) 一般都可以用 dict 和 getattrib 实现,我在找实现 exec(...) 办法。网上好像说 eval 和 exec 都可以用别的办法代替。
    ZRS
        3
    ZRS  
       2017-07-09 21:36:25 +08:00
    locals()["func_name"]
    josephshen
        4
    josephshen  
       2017-07-09 21:38:24 +08:00 via iPhone
    参见
    importlib.util.module_from_spec

    importlib.util.spec_from_file_location
    yucongo
        5
    yucongo  
    OP
       2017-07-09 21:39:00 +08:00
    @ZRS 感谢,我研究一下……
    yucongo
        6
    yucongo  
    OP
       2017-07-09 21:41:53 +08:00
    @josephshen 感谢,我 google 一下
    yucongo
        7
    yucongo  
    OP
       2017-07-09 23:16:02 +08:00
    @ZRS locals()["func_name"] 只是拿到 module 的名字,其实是源码里的 tmp, 可我要的是 module 的 方法(给定'pathlib' 和 'Path', 实现 from pathlib import Path)。

    @josephshen importlib.util.module_from_spec 和 importlib.util.spec_from_file_location 貌似都搜索 module 的名字。可我要的是 module 的 方法(例如,给定'pathlib' 和 'Path', 实现 from pathlib import Path)。
    yucongo
        8
    yucongo  
    OP
       2017-07-09 23:28:21 +08:00
    请各路高人继续支招,先感谢。

    我再简化一下问题,考虑下面的源码

    module_name = 'pathlib'
    tmp = importlib.import_module(module_name) # 等效 import pathlib; tmp = pathlib
    importlib.reload(tmp) # 等效 importlib.reload(pathlib)

    ? ?? # 如何不用 exec 实现 from pathlib import Path?

    # 用 exec 的话可以凑一个 execline = "Path = getattr(tmp, 'Path')" 送给 exec(execline)
    # 等效运行了 Path = getattrib(pathlib, 'Pah') , 等效于 from pathlib import Path
    lrxiao
        9
    lrxiao  
       2017-07-09 23:38:06 +08:00
    tmp.__dict__['Path']不行吗
    lrxiao
        10
    lrxiao  
       2017-07-09 23:46:03 +08:00
    等下 你要限定这个函数叫 Path。。。那我不知道了
    mckelvin
        11
    mckelvin  
       2017-07-09 23:52:55 +08:00
    josephshen
        12
    josephshen  
       2017-07-10 00:06:40 +08:00 via iPhone
    再直接 moudle.__dict__[fun_name]就可以了啊,我有种感觉你应该没什么 python 的经验……,那些函数只是普通变量,你获得函数变量后想怎么命名就怎么命名啊
    yucongo
        13
    yucongo  
    OP
       2017-07-10 01:15:18 +08:00
    感谢楼上各位。

    我想我知道怎么做了。8 楼问题的答案是:

    globals()['Path'] = getattrib(tmp, 'Path')

    0 楼的 exec 行可以用下面的码代替:

    globals()[modules[idx]] = getattrib(tmp, modules[idx])
    imn1
        14
    imn1  
       2017-07-10 08:14:12 +08:00
    google "动态导入模块"
    ledzep2
        16
    ledzep2  
       2017-07-10 16:21:10 +08:00
    感觉问题有点误导. 核心是如何替代 exec 里的 assign. 和 import module 啥的关系都不大.
    yucongo
        17
    yucongo  
    OP
       2017-07-10 17:43:58 +08:00
    @ledzep2 是啊,有些大侠不审题就给答案 ;), 而且提的问题里已经用了 importlib。不过还是感谢各位……
    josephshen
        18
    josephshen  
       2017-07-10 19:51:27 +08:00 via iPhone
    哈哈哈哈哈,原来你的核心问题就是如何动态创建一个名为 xxx 的变量。那 locals 和 globals 都可以,具体就看你想要的作用范围啦。哈哈哈哈哈
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1550 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:49 · PVG 00:49 · LAX 08:49 · JFK 11:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.