forked from tjwei/PythonTutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
varwatch.py
146 lines (137 loc) · 4.35 KB
/
varwatch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import cgi
try:
import reprlib #Python 3
except:
import repr as reprlib # Python2
from IPython.display import Javascript, display, HTML
__ip = None
html_content = """
<style>
table, th, td {
border: 5px solid black;
}
#watcher {
color: #500;
opacity: 0.7;
position: fixed;
height: auto;
width: 30%;
right: 0;
top:0;
z-index: 1000;
background: #ccc;
}
</style>
<script>
if($('#watcher').length == 0)
$( "body" ).append( '<div id="watcher" ></div>')
</script>
"""
def var_str():
import sys
ip = __ip
txt = []
user_ns = ip.user_ns
user_ns_hidden = ip.user_ns_hidden
nonmatching = object() # This can never be in user_ns
varnames = [ i for i in user_ns if not i.startswith('_') \
and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
varnames.sort()
seq_types = ['dict', 'list', 'tuple']
ndarray_type = None
if 'numpy' in sys.modules:
try:
from numpy import ndarray
except ImportError:
pass
else:
ndarray_type = ndarray.__name__
abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
def type_name(v):
tn = type(v).__name__
return abbrevs.get(tn,tn)
varlist = [ip.user_ns[n] for n in varnames]
typelist = []
for vv in varlist:
tt = type_name(vv)
if tt=='instance':
typelist.append( abbrevs.get(str(vv.__class__),
str(vv.__class__)))
else:
typelist.append(tt)
# column labels and # of spaces as separator
txt.append(['Variable', 'Type', 'Data/Info'])
# and the table itself
kb = 1024
Mb = 1048576 # kb**2
for vname,var,vtype in zip(varnames,varlist,typelist):
ent = [vname, vtype]
if vtype in seq_types:
txt.append(ent+[reprlib.repr(var)+" len="+str(len(var))])
elif vtype == ndarray_type:
vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
if vtype==ndarray_type:
# numpy
vsize = var.size
vbytes = vsize*var.itemsize
vdtype = var.dtype
vbytes_repr = vbytes
if vbytes >=100000:
if vbytes < Mb:
vbytes_repr = '(%s kb)' % (vbytes/kb,)
else:
vbytes_repr = '(%s Mb)' % (vbytes/Mb,)
txt.append(ent+[vbytes_repr])
else:
try:
vstr = str(var)
except UnicodeEncodeError:
vstr = unicode_type(var).encode(DEFAULT_ENCODING,
'backslashreplace')
except:
vstr = "<object with id %d (str() failed)>" % id(var)
vstr = vstr.replace('\n', '\\n')
if len(vstr) < 50:
txt.append(ent+[vstr])
else:
txt.append(ent+[vstr[:25] + "<...>" + vstr[-25:]])
return txt
def update_watcher(last_vars=dict()):
vhtml = "<table>"
var_list = var_str()
var_changes = dict()
next_vars = dict()
for tr in var_list:
next_vars[tr[0]]=(tr[1], tr[2])
if tr[0] not in last_vars:
var_changes[tr[0]]=(1,1,1)
else:
var_changes[tr[0]]=(0,next_vars[tr[0]][0]!=last_vars[tr[0]][0],next_vars[tr[0]][1]!=last_vars[tr[0]][1])
var_iter = iter(var_list)
tr = next(var_iter)
vhtml+= "<tr>"
for th in tr:
#style = ""
style=" style='color: #0f0;background: #555'"
vhtml+="<th%s>"%style+cgi.escape(str(th))+"</th>"
vhtml+="</tr>\n"
for tr in var_iter:
vhtml+= "<tr>"
changes = var_changes[tr[0]]
for i, td in enumerate(tr):
style = ""
if changes[i]:
style=" style='color: #f00;background: #0ff'"
vhtml+="<td%s>"%style+cgi.escape(str(td))+"</td>"
vhtml+="</tr>\n"
vhtml+="</table>"
display(Javascript("$('#watcher').html(\"%s\")"%vhtml.replace('\n','').replace('"',"")))
last_vars.clear()
last_vars.update(next_vars)
def load_ipython_extension(ipython):
global __ip
a = reprlib.aRepr
a.maxdict = a.maxlist = a.maxtuple = a.maxset = a.maxfrozenset = a.maxdeque = a.maxarray = 20
__ip=ipython
display(HTML(html_content))
ipython.events.register('post_execute', update_watcher)