Mr_*_*s_D 5 python python-import traceback python-2.7
我正在将一个巨大的 py 模块重构为包 - 为了不破坏现有代码,我将其内容移动到package/__init__.py模块(将代码添加到 __init__.py)并继续从那里拆分它。我注意到在某个时刻,在我的回溯中我得到:
Traceback (most recent call last):
File "<string>", line 656, in DoItemMenu
File "bash\balt.py", line 2109, in PopupMenu
link.AppendToMenu(menu,parent,*args)
File "bash\balt.py", line 2225, in AppendToMenu
for link in self.links: link.AppendToMenu(subMenu,window,data)
...
Run Code Online (Sandbox Code Playgroud)
其中的行File "<string>"对应于特定package/__init__.py模块。此外,PyCharm 的调试器显示“帧不可用”行,并且不会单步执行__init__.py. 为什么?与进口模式有关吗?
该代码由启动器类导入:
class UnicodeImporter(object):
def find_module(self,fullname,path=None):
if isinstance(fullname,unicode):
fullname = fullname.replace(u'.',u'\\')
exts = (u'.pyc',u'.pyo',u'.py')
else:
fullname = fullname.replace('.','\\')
exts = ('.pyc','.pyo','.py')
if os.path.exists(fullname) and os.path.isdir(fullname):
return self
for ext in exts:
if os.path.exists(fullname+ext):
return self
def load_module(self,fullname):
if fullname in sys.modules:
return sys.modules[fullname]
else:
sys.modules[fullname] = imp.new_module(fullname)
if isinstance(fullname,unicode):
filename = fullname.replace(u'.',u'\\')
ext = u'.py'
initfile = u'__init__'
else:
filename = fullname.replace('.','\\')
ext = '.py'
initfile = '__init__'
if os.path.exists(filename+ext):
try:
with open(filename+ext,'U') as fp:
mod = imp.load_source(fullname,filename+ext,fp)
sys.modules[fullname] = mod
mod.__loader__ = self
return mod
except:
print 'fail', filename+ext
raise
mod = sys.modules[fullname]
mod.__loader__ = self
mod.__file__ = os.path.join(os.getcwd(),filename)
mod.__path__ = [filename]
#init file
initfile = os.path.join(filename,initfile+ext)
if os.path.exists(initfile):
with open(initfile,'U') as fp:
code = fp.read()
exec code in mod.__dict__
return mod
Run Code Online (Sandbox Code Playgroud)
代码不是以传统方式导入的;相反,启动器代码使用加载文件的exec语句__init__.py。
减少load_module()包的启动器函数中的流程(因此不是模块的路径),您会得到以下结果:
# the fullname module isn't yet loaded
sys.modules[fullname] = imp.new_module(fullname)
initfile = '__init__' # or u'__init__' if a unicode path was used
# if no .py file was found, so not a module
mod = sys.modules[fullname]
mod.__loader__ = self
mod.__file__ = os.path.join(os.getcwd(),filename)
mod.__path__ = [filename]
#init file
initfile = os.path.join(filename,initfile+ext)
if os.path.exists(initfile):
with open(initfile,'U') as fp:
code = fp.read()
exec code in mod.__dict__
return mod
Run Code Online (Sandbox Code Playgroud)
这将创建一个空模块对象,手动加载源并将其作为字符串执行,并传入模块命名空间作为执行代码的全局变量。生成的代码对象始终会<string>在回溯中列出:
>>> import imp
>>> mod = imp.new_module('foo.bar')
>>> mod.__file__ = r'C:\some\location\foo\bar'
>>> mod.__path__ = [r'foo\bar']
>>> exec 'raise ValueError("oops")' in mod.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
ValueError: oops
Run Code Online (Sandbox Code Playgroud)
由于没有与代码关联的文件名,PyCharm 也无法找到原始源。
解决方法是首先使用该compile()函数创建一个代码对象,然后附加一个文件名:
>>> exec compile('raise ValueError("oops")', r'C:\some\location\foo\bar\__init__.py', 'exec') in mod.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\some\location\foo\bar\__init__.py", line 1, in <module>
ValueError: oops
Run Code Online (Sandbox Code Playgroud)
请注意,我__init__.py在文件名中包含了;将其转换回您要使用的启动器:
if os.path.exists(initfile):
with open(initfile,'U') as fp:
code = fp.read()
exec compile(code, initfile, 'exec') in mod.__dict__
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19707 次 |
| 最近记录: |