inspect: get the calling command

  • Thread starter Hans Georg Krauthaeuser
  • Start date
H

Hans Georg Krauthaeuser

Dear all,

I have a problem to get the command that has called a function if the
command was given on multiple lines. E.g.:

###################################################
import inspect

def call(a,b,c,d,e):
s = inspector()
return s

def inspector():
frame = inspect.currentframe()
outerframes = inspect.getouterframes(frame)
cmd = ''
for c in outerframes[2][4]:
cmd += c
return cmd

if __name__ == '__main__':
s1 = call (1,2,3,4,5)
s2 = call (1,\
2,\
3,\
4,\
5)
print '-'*10
print s1
print '-'*10
print s2
print '-'*10
###################################################

This gives the output:

----------
s1 = call (1,2,3,4,5)

----------
5)

----------

I'm quite new to python and the standard libs. So forgive me, if this is
a stupid question.

Any help is very much appreciated.

Best regards
Hans Georg
 
H

Hans Georg Krauthaeuser

Inyeol said:
It's an old bug. See Python bug [607092] at Sourceforge.

Inyeol
Thanks for pointing me there. Resolution for this bug is 'Wont Fix'. So,
did you have any idea how to work around that 'feature'. What I wanted
to have is some kind of autosave functionality. I have a class doing
some measurements which might take some days of time. At certain points,
I want to pickle the class instance (this is working) to a file. If the
measurement fails, e.g. due to a power main failure, I can recover from
the pickle file. Now, I want also to save the command that issued the
measurement in order to recover automatically with the right command.

BTW, are you sure that my problem is really due to that bug. I'm asking
because one comment stated: '...You should also check out current CVS,
seeing as there are no SET_LINENO instructions any more...'

Hans Georg
 
H

Hans Georg Krauthaeuser

I got a working solution by myself:

import inspect

def call(a,b,c,d,e):
s = inspector()
return s

def inspector():
frame = inspect.currentframe()
outerframes = inspect.getouterframes(frame)
ccframe = outerframes[2][0]
ccmodule = inspect.getmodule(ccframe)
try:
slines, start = inspect.getsourcelines(ccmodule)
except IOError:
clen = 10
else:
clen = len(slines)
finfo = inspect.getframeinfo(ccframe, clen)
theindex = finfo[4]
lines = finfo[3]
theline = lines[theindex]
cmd = theline
for i in range(theindex-1, 0, -1):
line = lines
try:
compile (cmd.lstrip(), '<string>', 'exec')
except SyntaxError:
cmd = line + cmd
else:
break
return cmd

if __name__ == '__main__':
s1 = call (1,2,3,4,5)
s2 = call (1,\
2,\
3,\
4,\
5)
print '-'*10
print s1
print '-'*10
print s2
print '-'*10
 
I

Inyeol Lee

.
Thanks for pointing me there. Resolution for this bug is 'Wont Fix'. So,
did you have any idea how to work around that 'feature'.

This is what I was doing. There might be better way.

1. get caller's source code using inspect.getsourcelines(traceback).
(Above function has a bug dealing with module-level traceback in
2.3.3. I'm not sure if it's fixed now.)
2. Tokenize the source up to traceback.tb_lineno.
3. Scan for last logical line break (token.NR ?).
BTW, are you sure that my problem is really due to that bug. I'm asking
because one comment stated: '...You should also check out current CVS,
seeing as there are no SET_LINENO instructions any more...'

Python 2.3.3 has the same bug (feature?). I didn't try 2.3.4.
2.3 doesn't use SET_LINENO bytecode, but uses traceback.tb_lineno instead.
It shows the same behavior.

Inyeol
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,743
Latest member
WoodrowMea

Latest Threads

Top