[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Timed execution in eval

alex.pedwysocki

3/7/2008 4:13:00 PM

I have various bits of code I want to interpret and run at runtime in
eval ...

I want to be able to detect if they fail with error, I want to be able
to time them, and I want to be able to stop them if they run too
long. I cannot add code to the eval'd strings that will help me
accomplish this.

Is there a good way to do this? I have it figured out for perl but
I'd rather use python if possible.

Thanks for any assistance.
9 Answers

Aaron Brady

3/7/2008 8:25:00 PM

0

On Mar 7, 10:12 am, alex.pedwyso...@gmail.com wrote:
> I have various bits of code I want to interpret and run at runtime in
> eval ...
>
> I want to be able to detect if they fail with error, I want to be able
> to time them, and I want to be able to stop them if they run too
> long.  I cannot add code to the eval'd strings that will help me
> accomplish this.
>
> Is there a good way to do this?  I have it figured out for perl but
> I'd rather use python if possible.
>
> Thanks for any assistance.

How does this sound? Write back if it's way far off from what you
want.

for line in break in put on line break
push in interactive console
extra linebreak at function ends
return list of functions?

... and I'll stop before I actually write it. Bets off!

Aaron Brady

3/7/2008 9:15:00 PM

0

On Mar 7, 10:12 am, alex.pedwyso...@gmail.com wrote:
> I have various bits of code I want to interpret and run at runtime in
> eval ...

import sys
from time import clock, sleep
from threading import Timer
TimeoutError= type('TimeoutError',(Exception,),{})

class Elapse:
def __init__( self ):
self.flag= False
def set( self ):
self.flag= True

def tr( frame, event, arg ):
if elapse.flag:
raise TimeoutError
return tr

def sleeper():
while 1:
sleep( .3 )
print( 'tick' )

def factercomp( n ):
val= 1
for i in range( 1, n ):
val*= i
return val

def facter( n ):
print( factercomp( n ) )

def runit( f, *ar ):
global elapse
elapse= Elapse()
t= Timer( 1, elapse.set )
t.start()
sys.settrace( tr )
try:
f( *ar )
except TimeoutError:
print( 'time elapse' )

runit( sleeper )
runit( facter, 10 )
runit( facter, 20 )
runit( facter, 10000 )
runit( facter, 100000 )

'''
tick
tick
tick
time elapse
362880
121645100408832000
time elapse
time elapse
'''

Steven D'Aprano

3/7/2008 10:07:00 PM

0

On Fri, 07 Mar 2008 08:12:38 -0800, alex.pedwysocki wrote:

> I have various bits of code I want to interpret and run at runtime in
> eval ...

I hope that code doesn't contain any data coming from an untrusted user.


> I want to be able to detect if they fail with error,

That's what try...except blocks are for.

try:
x = eval('1 + 1 = 2')
except SyntaxError:
x = 3


> I want to be able to time them,

That's what the timeit module is for.

If you do time them, you will find that eval(expr) is MUCH MUCH slower
than just executing expr as normal.

>>> from timeit import Timer
>>> Timer('1+1').timeit()
0.25557518005371094
>>> Timer('eval("1+1")').timeit()
21.816912174224854

If you use eval() a lot, you will have a SLOW program.


> and I want to be able to stop them if they run too long.

That's tricky. As far as I know, the only way for a Python program to
stop an arbitrary calculation after a certain period of time it to run it
in a thread. You then monitor the elapsed time, and when the timer
expires, ask the thread to die. And hope it listens.


> I cannot add code to the eval'd strings that will help me accomplish
> this.

You can't? Why ever not?

Note: that's almost certainly the wrong way to solve your problem, but
I'm curious as to why you can't.



--
Steven

Aaron Brady

3/8/2008 2:19:00 AM

0

On Mar 7, 4:07 pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> > I want to be able to detect if [certain threads] fail with error,
>
> You can't? Why ever not?

Try this. ext can be found in 'C Function in a Python Context' on
google groops.

import ext
extA= ext.Ext()
extA[ 'araise' ]= r"""
int araise( int a, PyObject* exc ) {
int res= PyThreadState_SetAsyncExc( a, exc);
return res;
}
""", ("i","i","O")

LastCallException= type( 'LastCallException', ( Exception, ),
{ 'canstayhere': True } )
import thread
import threading
import time
partystart= threading.Event()
doorsclose= threading.Event()
def thd():
partystart.set()
try:
while 1:
print( 'running, ha ha!' )
time.sleep( .2 )
except Exception:
print( '\nclean thread exit\n' )
finally:
doorsclose.set()

partyid= thread.start_new_thread( thd, () )
partystart.wait()
print( 'waiting a second\n' )
time.sleep( 1 )
ret= extA.araise( partyid, LastCallException )
doorsclose.wait( 1 )
if not doorsclose.isSet():
print( 'Tell me about it.' )
print( 'clean exit\n' )

'''
waiting a second
running, ha ha!
running, ha ha!
running, ha ha!
running, ha ha!
running, ha ha!
clean thread exit
clean exit
'''

George Sakkis

3/8/2008 3:44:00 AM

0

On Mar 7, 11:12 am, alex.pedwyso...@gmail.com wrote:
> I have various bits of code I want to interpret and run at runtime in
> eval ...
>
> I want to be able to detect if they fail with error, I want to be able
> to time them, and I want to be able to stop them if they run too
> long. I cannot add code to the eval'd strings that will help me
> accomplish this.
>
> Is there a good way to do this? I have it figured out for perl
> but I'd rather use python if possible.
>
> Thanks for any assistance.

Check out these two recipes:

- Using signals: http://aspn.activestate.com/ASPN/Cookbook/Python/Rec...

- Using threads: http://aspn.activestate.com/ASPN/Cookbook/Python/Rec...

Note that neither is perfect; the first breaks if the timed code
overrides the alarm signal, while the second can't interrupt code that
doesn't release the GIL and doesn't actually kill the function after
the timeout.

I'd be rather surprised if the perl solution you figured out doesn't
have any issues.

George

Aaron Brady

3/8/2008 9:07:00 AM

0

On Mar 7, 9:43 pm, George Sakkis <george.sak...@gmail.com> wrote:
> On Mar 7, 11:12 am, alex.pedwyso...@gmail.com wrote:
>
> > I have various bits of code I want to interpret and run at runtime in
> > eval ...
>
> Check out these two recipes:
>
> - Using signals:http://aspn.activestate.com/ASPN/Cookbook/Python/Rec...
>
> - Using threads:http://aspn.activestate.com/ASPN/Cookbook/Python/Rec...
>
> the second can't interrupt code that
> doesn't release the GIL and doesn't actually kill the function after
> the timeout.

Mine doesn't either, plus you need a C compiler. I also learned today
that one of the import statements doesn't find the dll on Py <3.0.

Do you have a process kill ability? That's another way to do it.

Guilherme Polo

3/8/2008 12:17:00 PM

0

2008/3/7, Steven D'Aprano <steve@remove-this-cybersource.com.au>:
> On Fri, 07 Mar 2008 08:12:38 -0800, alex.pedwysocki wrote:
>
> > I have various bits of code I want to interpret and run at runtime in
> > eval ...
>
>
> I hope that code doesn't contain any data coming from an untrusted user.
>
>
>
> > I want to be able to detect if they fail with error,
>
>
> That's what try...except blocks are for.
>
> try:
> x = eval('1 + 1 = 2')
> except SyntaxError:
> x = 3
>
>
>
> > I want to be able to time them,
>
>
> That's what the timeit module is for.
>
> If you do time them, you will find that eval(expr) is MUCH MUCH slower
> than just executing expr as normal.
>
> >>> from timeit import Timer
> >>> Timer('1+1').timeit()
> 0.25557518005371094
> >>> Timer('eval("1+1")').timeit()
> 21.816912174224854
>
> If you use eval() a lot, you will have a SLOW program.
>
>
>
> > and I want to be able to stop them if they run too long.
>
>
> That's tricky. As far as I know, the only way for a Python program to
> stop an arbitrary calculation after a certain period of time it to run it
> in a thread. You then monitor the elapsed time, and when the timer
> expires, ask the thread to die. And hope it listens.
>

Or you could use setitimer (not available for now). I opened an issue
at roundup to add setitimer and getitimer wrappers to the signal
module.
It would be great if you could test on your platform. It was done for
py3k, but could easily be back ported to python 2.6.

http://bugs.python.org...

>
>
> > I cannot add code to the eval'd strings that will help me accomplish
> > this.
>
>
> You can't? Why ever not?
>
> Note: that's almost certainly the wrong way to solve your problem, but
> I'm curious as to why you can't.
>
>
>
> --
>
> Steven
>
> --
> http://mail.python.org/mailman/listinfo/p...
>


--
-- Guilherme H. Polo Goncalves

Aaron Brady

3/10/2008 1:06:00 AM

0

> >  > and I want to be able to stop [functions] if they run too long.
>
> > That's tricky [due to a synthetic limitation].

It would suck if you couldn't hold the GIL for as long as you need
to. But how much is it used?

Wrote the docs:
> when two threads simultaneously increment the reference count of the same object

Well, the example sucked. Just synchronize ref count manipulation.
Every OS has locking primitives, and a library exists to deny requests
to block that lock dead. How integral is the GIL to Python?

> The Python interpreter is not fully thread safe

-Make- it so.

Aaron Brady

3/10/2008 1:30:00 AM

0

> Write the docs:
>
> > when two threads simultaneously increment the reference count of the same object
>
> Well, the example sucked.  Just synchronize ref count manipulation.
> Every OS has locking primitives, and a library exists to deny requests
> to block that lock dead.  How integral is the GIL to Python?
>
> > The Python interpreter is not fully thread safe
>
> Make it so.

Per-thread reference counts do the trick.