问题描述
我想获取源代码目录的模块:__main__
中的所有函数和类:/tmp/rebound/rebound
。
当我使用 pyclbr.readmodule_ex
API 时:
source_code_data = pyclbr.readmodule_ex(source_code_module,path=source_code_path)
我指定了模块和路径:
DEBUG:root:Source code module: __main__,Source code path: ['/tmp/rebound/rebound/rebound']
然后我收到此错误:
File "/Library/Developer/CommandLinetools/Library/Frameworks/python3.framework/Versions/3.8/lib/python3.8/importlib/util.py",line 69,in _find_spec_from_path
raise ValueError('{}.__spec__ is None'.format(name))
ValueError: __main__.__spec__ is None
然后我尝试使用不应该被公众使用的功能:_readmodule
:
source_code_data = pyclbr._readmodule(source_code_module,source_code_path,)
但我无法决定参数的值应该是什么:inpackage
。
def _find_spec_from_path(name,path=None):
"""Return the spec for the specified module.
First,sys.modules is checked to see if the module was already imported. If
so,then sys.modules[name].__spec__ is returned. If that happens to be
set to None,then ValueError is raised. If the module is not in
sys.modules,then sys.Meta_path is searched for a suitable spec with the
value of 'path' given to the finders. None is returned if no spec Could
be found.
Dotted names do not have their parent packages implicitly imported. You will
most likely need to explicitly import all parent packages in the proper
order for a submodule to get the correct spec.
"""
if name not in sys.modules:
return _find_spec(name,path)
else:
module = sys.modules[name]
if module is None:
return None
try:
spec = module.__spec__
except AttributeError:
raise ValueError('{}.__spec__ is not set'.format(name)) from None
else:
if spec is None:
raise ValueError('{}.__spec__ is None'.format(name))
return spec
这是模块中的函数:python3.8/importlib/util.py
,当它落在 __main__
块中时,它会将 else
评估为内置模块。
如何区分要读取的目标源代码的 __main__
和内置的 __main__
?换句话说,我如何读取代码库的模块__main__
:反弹?
解决方法
TL:DR
试试:
source_code_data = pyclbr.readmodule_ex("rebound.__main__",path=source_code_path)
说明
如您所知:_find_spec_from_path
将在 name
中搜索 sys.modules
并
__main__
始终存在。
如果您检查 sys.modules.keys()
,您会注意到它包含点分隔的模块名称。
来自 Ipython shell 的示例:
'IPython.display','IPython.extensions','IPython.extensions.storemagic','IPython.lib','IPython.lib.backgroundjobs','IPython.lib.clipboard','IPython.lib.display','IPython.lib.pretty','IPython.lib.security','IPython.paths',
如果您意识到您正在寻找 rebound.__main__
而不是 __main__
,这很明显。为了进入 if
块,name
不能在 sys.modules
中。最后一句是 _find_spec_from_path
没有错误。
# python3.8/importlib/util.py
def _find_spec_from_path(name,path=None):
# ...
if name not in sys.modules:
return _find_spec(name,path)
else:
#...