我正在尝试开发一个更简单的协议,用于在脚本运行之前,期间和之后记录我的工作环境的命名空间。显然,我在Python中可用的唯一东西是在运行脚本之前访问vars(),locals()或globals()字典,然后立即访问。这是中等成功的,在某种意义上我可以捕获命名空间添加(通过他们的键),但我无法知道各种实体添加到字典的顺序。如果没有手动对列表进行排序以生成时间顺序列表,那么在尝试确定命名空间的顺序时,我是否忽略了任何内容。下面是vars()词典的前后快照结果:
>>> # vars() keys before running script
>>> vars_keys_0 = vars().keys()
>>> for key in vars_keys_0:
... print('key: {:<15} - {}'.format(key,type(vars()[key])))
...
key: __builtins__ - <type 'module'>
key: __name__ - <type 'str'>
key: pywin - <type 'module'>
key: __doc__ - <type 'NoneType'>
key: __package__ - <type 'NoneType'>
>>>
>>> # vars() keys after running script
>>> vars_keys_1 = vars().keys()
>>> for key in vars_keys_1:
... print('key: {:<15} - {}'.format(key,type(vars()[key])))
...
key: rand_pnts - <class 'numpy.core.records.recarray'>
key: arr - <class 'numpy.core.records.recarray'>
key: random - <type 'module'>
key: extent_LRBT - <type 'function'>
key: pnts - <type 'list'>
..... snip ....
key: lineIntersect - <type 'function'>
key: from_XsYs - <type 'function'>
key: from_extent - <type 'function'>
key: Xs - <type 'list'>
key: vars_keys_0 - <type 'list'>
key: lineIntersect2 - <type 'function'>
>>>
步骤之间的差异很容易通过集合收集:
v1 = vars().keys() # at step 1
v2 = vars().keys() # at step 2 then
diff = set(v2).difference(set(v1)) # yields the difference in namespace
字典按预期无序排列,但我肯定错过了一些可以按顺序收集命名空间添加内容的内容。
编辑: 根据下面的附加建议,我尝试了这个简单的脚本来测试
import sys
def zipper(Xs,Ys):
'''zip two lists'''
return zip(Xs,Ys)
#--------------------------------------------------------------------
if __name__ == "__main__":
_order = []
_seen = set(vars())
def trace_names(frame, event, arg):
if event == 'call' and arg is None:
# enter first frame, return 'local' trace
return trace_names
if event in ('line', 'return'):
# (last) line in top-level frame executed
_order.extend(frame.f_globals.viewkeys() - _seen)
_seen.update(frame.f_globals)
sys.settrace(trace_names)
Xs = [0,0,2,2,0]
Ys = [1,3,3,1,1]
print('Zipped lists {}',format(zipper(Xs,Ys)))
sys.settrace(None)
print(_order)
遗憾的是,结果更令人困惑: ('Zipped lists {}','[(0,1),(0,3),(2,3),(2,1),(0,1)]') ['trace_names','_ seen','Xs','Ys','CmdTarget','Object','win32ui','default_scintilla_encoding','app','Queue','thread_test','WindowOutputDocument',' WindowOutputDocumentParent','re','window','WindowOutputViewScintilla','test','string','WindowOutput','scintillacon','docview','WindowOutputView','RTFWindowOutput','WindowOutputFrame',... ....'ScintillaControlInterface','EM_GETSELTEXT','EM_EXSETSEL','dllid','EM_EXLINEFROMCHAR','EM_FINDTEXTEX','ScintillaNotification','os']
如果def展示位置有误,请告知。
答案 0 :(得分:1)
跟踪订单的唯一方法是使用全面跟踪。您可以使用sys.settrace()
hook执行此操作,但是您必须将所有内容都移到main()
函数中,因为您无法将跟踪器附加到当前框架,只有新框架:
import sys
_order = []
_seen = set()
def trace_names(frame, event, arg):
if event == 'call' and arg is None:
# enter first frame, return 'local' trace
return trace_names
if event in ('line', 'return'):
# (last) line in top-level frame executed
_order.extend(frame.f_locals.viewkeys() - _seen)
_seen.update(frame.f_locals)
sys.settrace(trace_names)
# run your script
main()
sys.settrace(None)
print(_order)
这跟踪了下一个范围中添加的本地人的顺序;如果任何函数修改全局变量,则通过检查跟踪器中的globals()
,无法确定除整个组之外的确切顺序。