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

Discussion in 'Python' started by Daniel, Nov 18, 2008.

  1. Daniel

    Daniel Guest

    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
    Daniel, Nov 18, 2008
    #1
    1. Advertising

  2. Daniel

    Aaron Brady Guest

    On Nov 18, 3:59 pm, Daniel <> wrote:
    > 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.
    Aaron Brady, Nov 19, 2008
    #2
    1. Advertising

  3. Daniel

    Daniel Guest

    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.
    Daniel, Nov 19, 2008
    #3
  4. Daniel

    Aaron Brady Guest

    See below.

    On Nov 19, 8:02 am, Daniel <> wrote:
    > 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
    Aaron Brady, Nov 20, 2008
    #4
  5. Daniel

    Daniel Guest

    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
    Daniel, Nov 20, 2008
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. morrell
    Replies:
    1
    Views:
    925
    roy axenov
    Oct 10, 2006
  2. John Devlon
    Replies:
    3
    Views:
    2,314
    John Devlon
    Apr 16, 2008
  3. Gerald Britton
    Replies:
    1
    Views:
    258
    alex23
    Feb 3, 2011
  4. Gerald Britton
    Replies:
    0
    Views:
    212
    Gerald Britton
    Feb 1, 2011
  5. Adam Anderson
    Replies:
    6
    Views:
    116
    Gary Wright
    Nov 7, 2007
Loading...

Share This Page