怎么写才可以不用 exec?

2017-07-09 21:11:39 +08:00
 yucongo

一段源码

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 这种写法太丑也容易出错。

4386 次点击
所在节点    Python
18 条回复
264768502
2017-07-09 21:27:42 +08:00
用 locals?
yucongo
2017-07-09 21:34:37 +08:00
@264768502 大侠可不可以说仔细一点,感谢。

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

importlib.util.spec_from_file_location
yucongo
2017-07-09 21:39:00 +08:00
@ZRS 感谢,我研究一下……
yucongo
2017-07-09 21:41:53 +08:00
@josephshen 感谢,我 google 一下
yucongo
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
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
2017-07-09 23:38:06 +08:00
tmp.__dict__['Path']不行吗
lrxiao
2017-07-09 23:46:03 +08:00
等下 你要限定这个函数叫 Path。。。那我不知道了
mckelvin
2017-07-09 23:52:55 +08:00
josephshen
2017-07-10 00:06:40 +08:00
再直接 moudle.__dict__[fun_name]就可以了啊,我有种感觉你应该没什么 python 的经验……,那些函数只是普通变量,你获得函数变量后想怎么命名就怎么命名啊
yucongo
2017-07-10 01:15:18 +08:00
感谢楼上各位。

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

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

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

globals()[modules[idx]] = getattrib(tmp, modules[idx])
imn1
2017-07-10 08:14:12 +08:00
google "动态导入模块"
ToBeHacker
2017-07-10 10:16:15 +08:00
ledzep2
2017-07-10 16:21:10 +08:00
感觉问题有点误导. 核心是如何替代 exec 里的 assign. 和 import module 啥的关系都不大.
yucongo
2017-07-10 17:43:58 +08:00
@ledzep2 是啊,有些大侠不审题就给答案 ;), 而且提的问题里已经用了 importlib。不过还是感谢各位……
josephshen
2017-07-10 19:51:27 +08:00
哈哈哈哈哈,原来你的核心问题就是如何动态创建一个名为 xxx 的变量。那 locals 和 globals 都可以,具体就看你想要的作用范围啦。哈哈哈哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/374122

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX