2

I'm doing genetic programming framework and I need to be able to execute some string representing complete python programs. I'm using Python 2.7. I have a config class in which the primitive sets are defined. Lets say

class Foo():
    def a(self,x):
        return x

    def b(self,y):
        return y

I'm extracting the functions with the python inspect module and I want to create some executable source code with imports and everything. I end up with a string that looks like this

import sys

def a(x,y):
    return x

def b(y):
    return y

def main(x,y)
    lambda x,y: a(b(y),a(x,y))

main(*sys.argv)

My problem is that I don't know how to pass command line arguments to the string I'm running with eval(). How can I pass command line arguments to a source file I want to run with eval()?

Edit: There are millions of individuals so writing to a file is not a great option.

Edit: I made a mistake. The eval() method is used only for expressions and not statements so using exec() is the correct approach

George Kouzmov
  • 319
  • 4
  • 15
  • 2
    What exactly are you trying to `eval`? Also your class defs don't have self as first arguments. – mhlester Jan 13 '14 at 19:58
  • What do you mean by "individuals" in the phrase "execute individuals"? – Dan Jan 13 '14 at 19:59
  • 2
    @Dan I think he's killing people... genetically. Yikes! – mhlester Jan 13 '14 at 20:01
  • You could implement something using partials or dynamically crated function/code objects, but if you want to stick with building things with a string and `eval`, just make your string a `Formatter` and run `eval` on iterations of your formatted string. – Silas Ray Jan 13 '14 at 20:02
  • How are `a` and `b` to be extracted from `Foo()`? Your `a()` signature doesn't fit, btw. Since methods and functions in Python are first-class objects, you can just store references to them and call them as needed, no need to use `eval()` for that. – Martijn Pieters Jan 13 '14 at 20:11
  • Sorry, meant `string.Template`, not `Formatter`. – Silas Ray Jan 13 '14 at 20:13
  • Individuals is a term used in genetic programming to represent a generated program. I know I'm missing the self method but I used the class for the sake of showcase. What I'm doing is I'm having a class that has certain functionality I need and it's being extended by Foo() I didn't show it because it's not important. Through inspect python module I am extracting the source code the arguments and the names of the function. However I need to pass arguments to the eval() so I can execute the individual propperly – George Kouzmov Jan 13 '14 at 22:45

2 Answers2

4
eval("function_name")(arg1, arg2)

or if you have a list of arguments:

arguments= [arg1,arg2,arg3,something]
eval("function_name")(*arguments)
Alex
  • 5,759
  • 1
  • 32
  • 47
3

You have three options, roughly speaking. You can keep going with eval(),you could actually write the string as a file and execute it with subprocess.Popen(), or you could call the function something besides main() and call it after defining it with eval().

exec() way:

In the string you want to exec

main(#REPLACE_THIS#)

Function to evaluate

import string
def exec_with_args(exec_string,args):
    arg_string=reduce(lambda x,y:x+','+y,args)
    exec_string.replace("#REPLACE_THIS#", arg_string)

Subprocess way:

 import subprocess
 #Write string to a file
 exec_file=open("file_to_execute","w")
 exec_file.write(string_to_execute)
 #Run the python file as a separate process
 output=subprocess.Popen(["python","file_to_execute"].extend(argument_list),
     stdout=subprocess.PIPE)

Function Definition Way

In the string you want to exec

def function_name(*args):
    import sys

    def a(x,y):
        return x

    def b(y):
        return y

    def inner_main(x,y):
        lambda x,y: a(b(y),a(x,y))

    inner_main(*args)

Outer code

exec(program_string)
function_name(*args)
Dan
  • 12,157
  • 12
  • 50
  • 84
  • I'm generating 1 million individuals and more, writing to a file will slow down the process way too much I've kept it as a final option in case there is no other solution. I will try the solution and let you know. – George Kouzmov Jan 13 '14 at 22:13
  • @George Kouzmov: It sounds like you're doing some pretty crazy metaprogramming. Have you considered using lisp, which is designed for this kind of situation? – Dan Jan 13 '14 at 22:53
  • @George Kouzmov: I added another method, which I think may be superior to the first two. I don't know much about code generation, though, so let me know if you think it would work. – Dan Jan 13 '14 at 23:08
  • It's a proof of concept project. I'm using a DEAP framework for genetic programming which is doing most of the work. However I'm evaluating the individuals over a network hence the need of source code. Problem is DEAP doesn't provide that functionality so I want to generate the individuals so I can execute them easily without the need of the framework and all the frameworks I'm using are in python or at least the best ones so this is not an option. – George Kouzmov Jan 13 '14 at 23:08
  • Just 10 minutes ago I figured out the third solution however I found out that eval() has problem with function definitions you can only work with expressions so this is a mistake and I have to redefine my problem, apperanly exec is the better choice – George Kouzmov Jan 13 '14 at 23:13
  • I guess the sub-process way is the correct one to tackle the problem. The IO will slow down the process but it's not much different from using exec() . – George Kouzmov Jan 13 '14 at 23:20
  • @George Kouzmov: The subprocess method allows you to parallelize easily, too. See [this answer](http://stackoverflow.com/a/7224186/789750) and [this article](https://medium.com/building-things-on-the-internet/40e9b2b36148). – Dan Jan 13 '14 at 23:50