Decorator function to wrap a function? - python

I have to write a dummy function to get my code running on different systems, from which some don't have the needed packages. The function is wrapped and then called like a class-function. I am struggling with this problem, any ideas how to do that?
Here I got a short snippet, I import a python script ray.py which should contain this remote() function. The remote function has to take two arguments, without any usage.
Edit: The#ray.remote() wraps the run() function to be parallel executable. It doesn’t change the return of run(). On some systems ray is not supported and I want the same script to execute sequentially without changing anything. Therefore I import a ray-dummy instead of the real one. Now I want to write the ray.remote() to wrap the run() function in a way so that it’s callable with run.remote().
That may be a very inconvenient method to just sequentially execute a function, but necessary to achieve an easy integration for different systems.
# here the wrapped function
#ray.remote(arg1, arg2)
def run(x):
return x**2
# call it
squared = run.remote(2)

I got a working script, located in the ray.py file:
def remote(*args, **kwargs):
def new_func(func):
class Wrapper:
def __init__(self, f):
self.func = f
def remote(self, *arg):
out = self.func(*arg)
return out
ret = Wrapper(func)
return ret
return new_func

Related

Is it possible to hook C module function in python?

I have this code where "clr" and "Assembly" are parts of C library in Linux:
import clr
from System.Reflection import Assembly
import functools
def prefix_function(function, prefunction):
#functools.wraps(function)
def run(*args, **kwargs):
prefunction(*args, **kwargs)
return function(*args, **kwargs)
return run
def this_is_a_function():
print("Hook function called instead of the original!")
# This gives me error "attribute is read-only"
Assembly.GetEntryAssembly = prefix_function(
Assembly.GetEntryAssembly, this_is_a_function)
# Should print:
# "Hook function called instead of the original!"
Assembly.GetEntryAssembly()
Is it possible to somehow hook calling to static function "GetEntryAssembly()" as well as calls to any functions in C libraries ? I need to modify logic and return result of the original "GetEntryAssembly()". So, in the example above I wish to print "Hook function called" when call to GetEntryAssembly() is made.
I can't subclass, but could accept overwrite kind of "pointers" like in C code.
Also I tried this answer, but read-only attribute error occurs.

How to call a function within a function from a module

I'm having an issue when I attempt to unit test my code. I have a script named "compute_stats2.py" which contains a defined function "compute_stats" within a function "main" because I want to build in a command line argument within main later down the line. The functions used in compute_stats are all defined within main, but I excluded them for the sake of neatness, please let me know if you need to take a look at it. That being said I have been attempting to unit test (see code below) and every time I attempt to run the test this error occurs.
AttributeError: module 'compute_stats2' has no attribute 'compute_stats'
I'm wondering if I'm not calling the function correctly within the unit test code. Any suggestions on how to make that call better.
P.S. apologizes in advance if it's a really obvious fix, I'm not the strongest coder.
compute_stats2.py
def main():
def compute_stats(values):
if not values:
return None
else:
o_min=minimum_of_list(values)
o_max=values[-1]
o_avg=average_of_list(values)
o_median=median_of_list(values)
return(o_min, o_max, o_avg, o_median)
if __name__ == '__main__':
main()
test_compute_stats2.py
import unittest
import compute_stats2
class TestComputeStats2(unittest.TestCase):
def test_none_from_none(list):
ret = compute_stats2.compute_stats(None)
list.assertIsNone(ret)
def test_empty_list(list):
ret = compute_stats2.compute_stats([])
list.assertIsNone(ret)
def test_even_elements_list(list):
ret = compute_stats2.compute_stats([1,2,3,4])
list.assertEqual(ret, (1, 4, 2.5, 2.5))
def test_odd_elements_list(list):
ret = compute_stats2.compute_stats([1,2,12])
list.assertEqual(ret, (1, 12, 5, 2))
def test_single_element_list(list):
ret = compute_stats2.compute_stats([43])
list.assertEqual(ret, (43, 43, 43, 43))
compute_stats() is an inner function inside main(). Since you don't use it internally you can take it out
def main(): # can be removed if there is no other use
pass
def compute_stats(values):
if not values:
return None
else:
o_min=minimum_of_list(values)
o_max=values[-1]
o_avg=average_of_list(values)
o_median=median_of_list(values)
return(o_min, o_max, o_avg, o_median)
By the way, if the tests are inside class they need self as first parameter. You should also change list as parameter name, it's a built in name.
def test_none_from_none(self, test_list):
You've built a local function inside of main that is called compute_stats. The execution of compute_stats will only ever occur when main is called due to scoping rules. As a result you would need to import and run main if you were wanting to run compute_stats in it's current state.
It would be a good idea to move the compute_stats outside of main if you'd like to import it. You would no longer be building a local function that has scope limited under main.
e.g.
def compute_stats(val):
pass
def main():
pass

Passing arguments to python eval()

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
eval("function_name")(arg1, arg2)
or if you have a list of arguments:
arguments= [arg1,arg2,arg3,something]
eval("function_name")(*arguments)
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)

Run multiple functions in a for loop python

Here is the start of my program. I want a lot of the functions to be inside the for loop as seen in the 3rd function here. How do I go about this?
#!/usr/bin/env python
from rdflib import URIRef, Graph
from StringIO import StringIO
import subprocess as sub
class Wordnet():
def __init__(self, graph):
graph = Graph()
def process_file(self, file):
file = open("new_2.txt", "r")
return file
def line_for_loop(self, file):
for line in file:
def split_pointer_part(self, before_at, after_at, line):
before_at, after_at = line.split('#', 1)
return before_at, after_at
def split_word_part(self, word_part, line):
word_part = line.split()
return word_part
Is it just a matter of indenting everything else in the for loop or is it when the function are called that the loop has to be defined?
How does one go about calling multiple functions as part of a program? I am new to python and i don't really know.
There's no program here. Classes by themselves don't do anything. You need to instantiate the class, then call one of its methods (which is the correct term for what you seem to be calling "processes"). So, at the end of this file, you might do:
wordnet = Wordnet()
my_file = wordnet.process_file()
wordnet.line_for_loop(my_file)
Inside one method, you can call another: so for your loop, you would do:
def line_for_loop(self, file):
for line in file:
self.my_method_1()
self.my_method_2()
There are some other issues with your code. For example, in the __init__ method, you define a graph local variable, but never do anything with it, so it is not stored anywhere. You need to store variables on self for them to become instance properties:
def __init__(self):
self.graph = Graph()
Also, you seem to be confused about when to pass parameters to functions. Twice (in __init__ and process_file) you accept a parameter, then override it inside the method with a local variable. If you're defining the variable in the function, you shouldn't pass it as a parameter.
Note that, as I've had occasion to say before, Python is not Java, and doesn't always require classes. In this case, the class is not contributing anything to the program, other than as a holder for methods. In Python, you would normally just use functions inside a module for that.
Process isn't the proper term to use. Those are better known as functions or methods. As far as Python loops go, indentation is important. You do need to indent.
def line_for_loop(self, file):
for line in file:
process_file("example_file_name.txt")
split_pointer_part(0, 10, "some test string")
You should make the function calls from inside the loop. The example code above may not be the exact solution for you code, but it should be sufficient enough to answer your question.

Print function calls with a variable delay / Python

The question is, how can I configure the Python debugger to show me in the console what functions are being called?
In order not to see everything flash by, a delay between the function calls would be needed.
If you want to monitor when a few particular functions are being called,
you could use this decorator:
import functools
def trace(f):
#functools.wraps(f)
def wrapper(*arg,**kw):
'''This decorator shows how the function was called'''
arg_str=','.join(['%r'%a for a in arg]+['%s=%s'%(key,kw[key]) for key in kw])
print "%s(%s)" % (f.__name__, arg_str)
return f(*arg, **kw)
return wrapper
You would use it like this:
#trace # <--- decorator your functions with the #trace decorator
def foo(x,y):
# do stuff
When you run your program, every time foo(x,y) is called, you'll see the
function call with the value of its arguments in the console:
foo(y=(0, 1, 2),x=(0, 0, 0))
You can use the alternative pydb debugger. You can invoke it with pydb --fntrace --batch <scriptname> to get a function trace.
As for the "flashing-by", use the usual tools like Ctrl-S/Ctrl-Q on an ANSI terminal, or redirect to a file.

Categories

Resources