Created
October 15, 2016 05:29
-
-
Save csm10495/39dde7add5f1b1e73c4e8299f5df1116 to your computer and use it in GitHub Desktop.
A really speedy way to get the current stack frame in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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