I'm using Python 3.6, I have a file called file.py, with have this two functions:
def country(countryName):
print(countryName)
def capital(capitalName):
print(capitalName)
I need to call any of these two methods from Command Line, but sincerely I don't know how to do that, also with arguments in this way.
python file.py <method> <argument>
Does someone knows how to do that?
Greetings!
To use command line arguments in a program you can use sys.argv. Read more
import sys
def country(countryName):
print(countryName)
def capital(capitalName):
print(capitalName)
method_name = sys.argv[1]
parameter_name = sys.argv[2]
getattr(sys.modules[__name__], method_name)(parameter_name)
To run the program:
python file.py capital delhi
output:
delhi
Your input parameter method_name is a string so can't be called directly. Hence we need to fetch the method handle using getattr.
Command sys.modules[__name__] fetches the current module. which is file.py module. Then we use getattr to fetch the method we want to call and call it. we pass the parameter to the method as `(parameter_name)'
you could have a module that inspects your file.py, call it executor.py, and adjust your methods in file.py to handle argument lists
executor.py:
import file
import sys
method = file.__dict__.get(sys.argv[0])
method(sys.argv[1:-1])
Related
Using the very interesting answer provided here, I would like to be able to use argparse and execute multiple functions without having to define the arguments to each function. Otherwise the code is very overloaded or one has to multiply files to run different functions, which is not very practical either.
In the following example, the functions function1 and function2 have different arguments such as: function1(arg1: int, arg2: bool) and function2(arg3: float, arg4: str)
# file test.py
import argparse
from file1 import function1
from file2 import function2
FUNCTION_MAP = {'function1' : function1, 'function2': function2}
parser = argparse.ArgumentParser()
parser.add_argument('command', choices=FUNCTION_MAP.keys())
# no specific argument to add here.
args = parser.parse_args()
func = FUNCTION_MAP[args.command]
func(**vars(args))
The following commands with -- arguments do not work.
python test.py "function1" --arg1=10 --arg2=True
python test.py "function2" --arg3=2.4 --arg4="a_file.csv"
command as python test.py "function1" works but asks me the arguments of the function1.
Thanks for your help.
If functions will be shuttling around/sharing lots of the same data, sounds like you want a class/object?
myobj.fn1() and myobj.fn2() will both have implicit access to the myobj object's data.
Use argparse input to define the initial instance via your class' __init__(self, x, y ...) method.
I'm writing a wrapper or pipeline to create a tfrecords dataset to which I would like to supply a function to apply to the dataset.
I would like to make it possible for the user to inject a function defined in another python file which is called in my script to transform the data.
Why? The only thing the user has to do is write the function which brings his data into the right format, then the existing code does the rest.
I'm aware of the fact that I could have the user write the function in the same file and call it, or to have an import statement etc.
So as a minimal example, I would like to have file y.py
def main(argv):
# Parse args etc, let's assume it is there.
dataset = tf.data.TFRecordDataset(args.filename)
dataset = dataset.map(args.function)
# Continue with doing stuff that is independent from actual content
So what I'd like to be able to do is something like this
python y.py --func x.py my_func
And use the function defined in x.py my_func in dataset.map(...)
Is there a way to do this in python and if yes, which is the best way to do it?
Pass the name of the file as an argument to your script (and function name)
Read the file into a string, possibly extracting the given function
use Python exec() to execute the code
An example:
file = "def fun(*args): \n return args"
func = "fun(1,2,3)"
def execute(func, file):
program = file + "\nresult = " + func
local = {}
exec(program, local)
return local['result']
r = execute(func, file)
print(r)
Similar to here however we must use locals() as we are not calling exec in global scope.
Note: the use of exec is somewhat dangerous, you should be sure that the function is safe - if you are using it then its fine!
Hope this helps.
Ok so I have composed the answer myself now using the information from comments and this answer.
import importlib, inspect, sys, os
# path is given path to file, funcion_name is name of function and args are the function arguments
# Create package and module name from path
package = os.path.dirname(path).replace(os.path.sep,'.')
module_name = os.path.basename(path).split('.')[0]
# Import module and get members
module = importlib.import_module(module_name, package)
members = inspect.getmembers(module)
# Find matching function
function = [t[1] for t in members if t[0] == function_name][0]
function(args)
This exactly solves the question, since I get a callable function object which I can call, pass around, use it as a normal function.
Assume, I have created an python file (FirstFile.py) name which contains many functions and other things. One of the function is this (of course, it is simplified):
def func(string):
assert eval(string)
Besides, I have created an python file which imports func() from the file mentioned above. Then this second python file try to execute following process:
from FirstFile import func
amk = 1
func("amk == 1")
When variable "amk" is in the first file, no problem reveals. However, when variable "amk" is in the second file, which is illustrated here, an error reveals:
NameError: name 'amk' is not defined
Would you like to please help me solve this problem?
by default eval executes in the current local/global scope, if you want to specify a different environment you can do something like:
eval("x == 1", {"x":1})
so your function could take an optional environ argument:
def func(string, environ=None):
assert eval(string, environ)
then you can call the function from the other module passing locals() as the environment:
from FirstFile import func
amk = 1
func("amk == 1", locals())
As a side note I'd recommend against evaluating arbitrary code especially if it is coming from another source / module as it could accidentally contain harmful code.
I am writing a python program where in I have included another python file.
The python file included has a method which I want to invoke from the calling script.
Like:
#!/usr/bin/python
include script1
method = sys.argv[1] # values may be - create or destroy
if method == "create":
script1.create()
elif method == "destroy":
script1.destroy()
Now, what I want is,
#!/usr/bin/python
include script1
method = sys.argv[1] # values may be - create or destroy
script1.method()
and, it should use the value inside the variable method instead of trying to call the module called method.
You can use getattr.
method= sys.argv[1]
getattr(script1, method)()
To call functions from script1, you could turn it into a module.
script1.py:
def create():
pass
def destroy():
pass
script2.py:
import script1
script1.create()
script1.destroy()
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)