连续脚本运行之间的python中的vars()字典

时间:2014-12-25 10:18:54

标签: python dictionary namespaces

我正在尝试开发一个更简单的协议,用于在脚本运行之前,期间和之后记录我的工作环境的命名空间。显然,我在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展示位置有误,请告知。

1 个答案:

答案 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(),无法确定除整个组之外的确切顺序。