Skip to content

Instantly share code, notes, and snippets.

@csm10495
Created October 15, 2016 05:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csm10495/39dde7add5f1b1e73c4e8299f5df1116 to your computer and use it in GitHub Desktop.
Save csm10495/39dde7add5f1b1e73c4e8299f5df1116 to your computer and use it in GitHub Desktop.
A really speedy way to get the current stack frame in Python
'''
Brief:
This script demonstrates how to get the current stack frame in a way faster than using
inspect.stack()... which is really slow (like ~450 times slower than this solution in most cases)
If the fast solution won't work, will fall back to an inspect.stack() solution.
Author:
Charles Machalow
'''
import inspect, sys, timeit
def getStackFrame(num, useGetFrame=True):
'''
Brief:
Gets a stack frame with the passed in num on the stack.
If useGetFrame, uses sys._getframe (implementation detail of Cython)
Otherwise or if sys._getframe is missing, uses inspect.stack() (which is really slow).
'''
# Not all versions of python have the sys._getframe() method.
# All should have inspect, though it is really slow
if useGetFrame and hasattr(sys, '_getframe'):
frame = sys._getframe(0)
frames = [frame]
while frame.f_back is not None and len(frames) <= num:
frames.append(frame.f_back)
frame = frame.f_back
return frames[num]
else:
return inspect.stack()[num].frame
def getThisStackFrame(useGetFrame=True):
"""
Brief:
Returns the current stack frame
"""
try:
return getStackFrame(2, useGetFrame)
except:
return getStackFrame(1, useGetFrame)
def avgTimeit(stmt='pass', number=1):
'''
Brief:
Code used to time a function for number amount of iterations.
Also gives the average time per run.
'''
totalSecs = timeit.timeit(stmt=stmt, number=number)
avgSecs = totalSecs / number
print ('Total Seconds for %d runs: %f' % (number, totalSecs))
print ('Average Seconds for each run: %f' % (avgSecs))
if __name__ == '__main__':
'''
Brief:
Test code
'''
print ("Using sys._getframe():")
avgTimeit(lambda: (getThisStackFrame(True)), number=5000)
print ("Using inspect.stack():")
avgTimeit(lambda: (getThisStackFrame(False)), number=5000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment