By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,813 Members | 1,130 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,813 IT Pros & Developers. It's quick & easy.

how to acces the block inside of a context manager as sourcecode

P: n/a
Hello,

I need to access the code inside of a context manager, i.e. the call to

with myManager(v=5) as x:
a=b
c=sin(x)
should cause the following output (minus the first line, if that's easier):
with myManager(v=5) as x: # I could live without this line
a=b
c=sin(x)
I can get the line number from the traceback (see below), and try to
find the block in the source, but that seems ugly to me.

class MyManager(object):
def __init__(self,name='name'):
# how to access the source code inside of the with block ?
f = traceback.extract_stack()
print f[0]

def __enter__(self):
pass

def __exit__(self,type,value,traceback):
if type is not None:
print 'exception'
pass

Any ideas?

Daniel
Nov 18 '08 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On Nov 18, 3:59*pm, Daniel <inva...@invalid.invalidwrote:
Hello,

I need to access the code inside of a context manager, i.e. the call to

with myManager(v=5) as x:
* * * * a=b
* * * * c=sin(x)

should cause the following output (minus the first line, if that's easier):

with myManager(v=5) as x: # I could live without this line
* * * * a=b
* * * * c=sin(x)

I can get the line number from the traceback (see below), and try to
find the block in the source, but that seems ugly to me.

class MyManager(object):
* * def __init__(self,name='name'):
* * * * # how to access the source code inside of the with block ?
* * * * f = traceback.extract_stack()
* * * * print f[0]

* * def __enter__(self):
* * * * pass

* * def __exit__(self,type,value,traceback):
* * * * if type is not None:
* * * * * * print 'exception'
* * * * pass

Any ideas?

Daniel
There isn't a solution in the general case, because strings can be
executed. However, 'inspect.currentframe()' and
'inspect.getsourcelines(object)' can handle some cases, and your idea
is (I believe) how getsourcelines works itself. You can probably do
it without a context manager, e.g. 'print_next_lines( 5 )' or
'print_prior_lines( 2 )', dedenting as needed.
Nov 19 '08 #2

P: n/a
Hi Aaron,

let me give you the reason for the context manager:
I am driving handware with a python script, basically a data acquisition
program which looks like this:
with dataStore('measurement1.dat') as d:
magnet.setField(0)
r1=doExperiment(voltage=0.345, current=0.346, temperature=33)
magnet.setField(1)
r2=doExperiment(voltage=0.32423, current=0.3654, temperature=45)
d.append(r2-r1)

the script does the measuring and the context manager stores the result
(r1 and r2), at the end the result is printed.

The source code serves as the documentation (it contains many parameters
that need to be well documented), so I print the source code, cut it out
and glue it into my lab notebook.
Now I want to automate this process, i.e. the dataStore should print the
sourcecode.

Daniel
There isn't a solution in the general case, because strings can be
executed. However, 'inspect.currentframe()' and
'inspect.getsourcelines(object)' can handle some cases, and your idea
is (I believe) how getsourcelines works itself. You can probably do
it without a context manager, e.g. 'print_next_lines( 5 )' or
'print_prior_lines( 2 )', dedenting as needed.
Nov 19 '08 #3

P: n/a
See below.

On Nov 19, 8:02*am, Daniel <inva...@invalid.invalidwrote:
Hi Aaron,

let me give you the reason for the context manager:
I am driving handware with a python script, basically a data acquisition
program which looks like this:

with dataStore('measurement1.dat') as d:
* * * * magnet.setField(0)
* * * * r1=doExperiment(voltage=0.345, current=0.346, temperature=33)
* * * * magnet.setField(1)
* * * * r2=doExperiment(voltage=0.32423, current=0.3654, temperature=45)
* * * * d.append(r2-r1)

the script does the measuring and the context manager stores the result
(r1 and r2), at the end the result is printed.

The source code serves as the documentation (it contains many parameters
that need to be well documented), so I print the source code, cut it out
and glue it into my lab notebook.
Now I want to automate this process, i.e. the dataStore should print the
sourcecode.

Daniel
There isn't a solution in the general case, because strings can be
executed. *However, 'inspect.currentframe()' and
'inspect.getsourcelines(object)' can handle some cases, and your idea
is (I believe) how getsourcelines works itself. *You can probably do
it without a context manager, e.g. 'print_next_lines( 5 )' or
'print_prior_lines( 2 )', dedenting as needed.

Hi. It is not the role of a 'dataStore' object in your object model,
which is why, ideally, you would separate those two functions.
However, if 'dataStore' always needs the printing functionality, you
could built it in for practical reasons. That has the benefit that
you don't need to specify, such as 'print_next_lines( 5 )', how many
lines to print, since the context manager can count for you, and if
you add a line, you won't need to change to 'print_next_lines( 6 )'.
Lastly, you could use two con. managers, such as:

with printing:
with dataStore('measurement1.dat') as d:
magnet.setField(0)

You may or may not find that relevant.

Here is some code and output:

import inspect
class CM( object ):
def __enter__(self):
self.startline= inspect.stack( )[ 1 ][ 0 ].f_lineno
def __exit__(self, exc_type, exc_value, traceback):
endline= inspect.stack( )[ 1 ][ 0 ].f_lineno
print self.startline, endline

with CM(): #line 9
a= 0
b= 1
c= 2

with CM(): #line 14
d= 3
e= 4

/Output:

9 12
14 16
Nov 20 '08 #4

P: n/a
Hi Aaron,

the dataStore combines both the printing and analysis (it will create a
report).
Unfortunately the end of the block already needs to be known in
__enter__, as the report starts to print during the measurement.
I decided to do it the following way:

__enter__ gets the start line number using the idea you proposed.
then the program reads the number of lines that are indented with
respect to the with block. This could cause problems for strange
indenting, but this should not happen in my application. Unfortunately I
could not use the ast module, because the comments are an important part
of the report.

Thank you for your ideas

Daniel


class CM( object ):
def __enter__(self):
self.startline= inspect.stack( )[ 1 ][ 0 ].f_lineno
print 'startline',self.startline
filename = inspect.stack( )[-1][1]

def getIndentation(line):
# TODO: handle comments and docstrings correctly
return len(line) - len(line.lstrip())

with open(filename,'r') as f:
lines=f.readlines()[self.startline-1:]
indent0=getIndentation(lines[0])
indent =[getIndentation(i)-indent0 for i in lines[1:]]
nlines = [n for l,n in zip(indent,xrange(1,1000000)) if l >
0][0]
self.callingCode = lines[:self.startline+nlines]

print self.callingCode
def __exit__(self, exc_type, exc_value, traceback):
pass

if __name__ == '__main__':
with CM():
print 'in first'
a= 0
b= 1
c= 2
print 'end of first'

with CM():
d= 3
e= 4
Nov 20 '08 #5

This discussion thread is closed

Replies have been disabled for this discussion.