sor*_*imo 12 python python-module inspection
我正在尝试确定函数的实际当前模块(如果从其他地方导入,则会看到),即使当前模块是" 顶级脚本环境 " __main__.
这可能听起来像一个奇怪的事情,但背景是我需要序列化一个函数并在不同的机器上反序列化它(包括参数),为此我需要确保__main__在反序列化之前导入正确的模块AND NOT (否则我得到一个错误说AttributeError: 'module' object has no attribute my_fun).
到目前为止,我已经尝试过检查:
import inspect
print inspect.getmodule(my_fun)
Run Code Online (Sandbox Code Playgroud)
这给了我
<module '__main__' from 'example.py'>
Run Code Online (Sandbox Code Playgroud)
当然.我也试过找一些有用的东西globals(),没有运气.
我真正想要的是<module 'example' from 'example.py'>.我想一个hacky方法是使用类似的东西从文件名解析它
m_name = __main__.__file__.split("/")[-1].replace(".pyc","")
Run Code Online (Sandbox Code Playgroud)
然后按名称查找模块sys.modules[m_name].
有更干净/更好的方法吗?
编辑:在了解了ipython的"FakeModule"以及更多谷歌搜索后,我发现了这篇文章,它正好描述了我面临的问题,包括我当前的解决方案(明确导入当前模块import current_module并序列化current_module.my_fun而不是my_fun).我试图避免这种情况,因为对我的软件包的用户来说可能不太直观.
小智 7
我知道这已经过时但我发现Python3中的一个更简单的解决方案对我有用.简而言之,对象的__spec__也存储实际的模块名称而不是"__main__".
import inspect
if obj.__class_.__module__ == "__main__":
print(inspect.getmodule(obj).__spec__.name)
Run Code Online (Sandbox Code Playgroud)
编辑:回想起来,到目前为止,最好和最干净的解决方案是避免首先出现这种情况; 如果它是您的序列化代码,请将所有可序列化函数移动到主程序脚本加载的模块.这使得函数的起源可以在任何和所有情况下检索,而不需要任何黑客或特殊情况.
如果那是不可能的,我认为您的原始解决方案(从中检索模块名称__main__.__file__)是最好和最简单的.如果您担心它对您的用户来说似乎是违反直觉的,请将其包装在一个很好的功能中并记录它的用途.
当你运行一个模块时__main__,python确实没有将它与它的正常模块名称相关联:如果你import example,它将第二次加载文件,就像它是一个单独的模块一样.事实上,这可能发生在您的情况下,否则您将无法通过名称找到您的模块sys.modules:模块example和模块__main__实际上是单独的运行时对象,因为您将发现是否明确更改其中一个模块变量.
我实际遇到了同样的问题.
我用的是:
return os.path.splitext(os.path.basename(__main__.__file__))[0]
Run Code Online (Sandbox Code Playgroud)
这实际上与你的"黑客"相同.老实说,我认为这是最好的解决方案.
| 归档时间: |
|
| 查看次数: |
3023 次 |
| 最近记录: |