Timed execution in eval

  • Thread starter alex.pedwysocki
  • Start date
A

alex.pedwysocki

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.
 
C

castironpi

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!
 
C

castironpi

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
'''
 
S

Steven D'Aprano

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.
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.
 
C

castironpi

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
'''
 
G

George Sakkis

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/Recipe/307871

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

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
 
C

castironpi

Check out these two recipes:

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

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

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.
 
G

Guilherme Polo

2008/3/7 said:
I hope that code doesn't contain any data coming from an untrusted user.





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

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





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.

21.816912174224854

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





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/issue2240
 
C

castironpi

 > 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.
 
C

castironpi

Write the docs:
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?


Make it so.

Per-thread reference counts do the trick.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top