Use Python command line argument as function names and function values - python-2.7

Related to this question Command line arguments in python.
With the SYS module, how can I use a command line argument as a function name and function value, within my code - without importing some other module?
I'd like a solution that uses sys only. Also, please no variable-length params answers. Those are confusing. Assume that just the function name and one function variable are specified at the command line.
import sys
def reversal(aaa): return aaa[::-1]
a = sys.argv[1]
b = sys.argv[2]
print a(b)
At the command line
cpu_location$ python blah.py reversal 'abcdefg'
Traceback (most recent call last):
File "blah.py", line 8, in <module>
print a(b)
TypeError: 'str' object is not callable
I want to know how to make sys.argv[1] be considered a function name, thereby calling the function I have defined.
The other posts I see on this are a mash up of:
- dealing with C/C++ and adding some other module
- not using sys at all
- using the argv items as values for functions, and names of other files, instead of names of functions

Better than the eval solution would be:
a = globals()[sys.argv[1]]
a(b)
globals() returns a dictionary mapping global variables names to those global variables. So globals()['reversal'] evaluates to the reversal function.
It's safer than the eval function. With your approach you could do something like:
python blah.py 'lambda x: x+"hi"' foobar
Which would print foobarhi, which is unexpected because that's not a function name.

2 hours later, I find the answer. I think it's worth it to post it here in a very simple fashion.
Basiclaly there is no "function" data type in Python, but someone did mention a function eval, which is built-in. Execute python commands passed as strings in command line using python -c (No -c is needed for my own example)
The solution, is to change
a = sys.argv[1]
to
a = eval(sys.argv[1])
This will make the passed in word, reversal, be evaluated. It will evaluate to a function. Then the a(b) call will be a perfect call of a function on a string, like how it's defined. Output will be like:
cpu_location$ python blah.py reversal unquoted
detouqnu
cpu_location$ python blah.py reversal 'withquotes'
setouqhtiw

use google module: fire
pip install fire
Here's a simple example:
import fire
class Calculator(object):
"""A simple calculator class."""
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Then, from the command line, you can run:
python calculator.py double 10 # 20
python calculator.py double --number=15 # 30

Related

Run Matlab script from Python: TypeError: 'float' object is not iterable

Actually I have a problem when calling a Matlab script from Python.
import matlab.engine
import os
import random
import numpy as np
a=[str(random.randint(1,3)) for _ in range(3)]
print(a)
eng=matlab.engine.start_matlab()
eng.cd("/Users/dha/Documents/MATLAB/test-matlab/",nargout=0)
sr, state=eng.test_func()
print(sr)
print(state)
In fact I want to return "sr" which is a float and an array of integer "state", e.g. sr = 34.31 and state = [1,2,5]. The function test_func() work well on Matlab, but when I run this in Python from terminal (python test_matlab_engine.py) I received the following error:
Traceback (most recent call last):
File "test_matlab_engine.py", line 10, in <module>
sr, state=eng.mabuc_drl(a)
TypeError: 'float' object is not iterable
Anyone please give me the solution. Thank you so much in advance.
It seems that the result from MATLAB to Python has been cut off. If you have two parameters, you only get one which is the first parameter from the MATLAB. So, the question is how to get two or more parameters.
In a word, you should write this in your Python file:
re = eng.your_function_name(parameter1, parameter2, nargout=2)
where re contains two parameters which come from MATLAB.
You can find more information in the official documentation: Call MATLAB Functions from Python

Call functions within a python script and pass arguments using command line

I have a script named first_code.py
The code in the script looks like
def function1(param1):
return var1
def function2(param1):
return var2
def function3(param1):
return var3
I want to execute the script first_code.py from the windows command like and pass the value of the param1 such that: all the functions get executed or if I want to execute a specific function say function2.
How can I do that?
You could use something like this to have a more generalized way to call a function the takes 0-* params :
if __name__ == '__main__':
print (len(sys.argv))
params = []
if len(sys.argv) > 2:
for x in range(2, len(sys.argv)):
params.append(sys.argv[x])
if len(params) > 0:
globals()[sys.argv[1]](*params)
else:
globals()[sys.argv[1]]()
If your script 'getstuff.py' included a function named 'getSomething(forWho, fromWho)' it
can be called:
python getstuff.py getsomething "Ray" "Steve"
Can take as many parameters as you want.
Just include the snippet in you script.:>)
The arguments you specify in command line are kept in sys.argv
you should add the following lines in the bottom of the code:
print function1(sys.argv[1])
print function2(sys.argv[1])
print function3(sys.argv[1])
please note sys.argv[0] is the script name.
If you want to specify the functions to be run add more arguments, they will be in sys.argv[2], sys.argv[3] etc'

Python-Console (Anaconda 4.2.0 (64-bit)): Input is not taken as string but "variable"? [duplicate]

I am getting an error when I try to run this simple script:
input_variable = input("Enter your name: ")
print("your name is" + input_variable)
Let's say I type in "dude", the error I am getting is:
line 1, in <module>
input_variable = input("Enter your name: ")
File "<string>", line 1, in <module>
NameError: name 'dude' is not defined
I am running Mac OS X 10.9.1 and I am using the Python Launcher app that came with the install of Python 3.3 to run the script.
TL;DR
input function in Python 2.7, evaluates whatever your enter, as a Python expression. If you simply want to read strings, then use raw_input function in Python 2.7, which will not evaluate the read strings.
If you are using Python 3.x, raw_input has been renamed to input. Quoting the Python 3.0 release notes,
raw_input() was renamed to input(). That is, the new input() function reads a line from sys.stdin and returns it with the trailing newline stripped. It raises EOFError if the input is terminated prematurely. To get the old behavior of input(), use eval(input())
In Python 2.7, there are two functions which can be used to accept user inputs. One is input and the other one is raw_input. You can think of the relation between them as follows
input = eval(raw_input)
Consider the following piece of code to understand this better
>>> dude = "thefourtheye"
>>> input_variable = input("Enter your name: ")
Enter your name: dude
>>> input_variable
'thefourtheye'
input accepts a string from the user and evaluates the string in the current Python context. When I type dude as input, it finds that dude is bound to the value thefourtheye and so the result of evaluation becomes thefourtheye and that gets assigned to input_variable.
If I enter something else which is not there in the current python context, it will fail will the NameError.
>>> input("Enter your name: ")
Enter your name: dummy
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'dummy' is not defined
Security considerations with Python 2.7's input:
Since whatever user types is evaluated, it imposes security issues as well. For example, if you have already loaded os module in your program with import os, and then the user types in
os.remove("/etc/hosts")
this will be evaluated as a function call expression by python and it will be executed. If you are executing Python with elevated privileges, /etc/hosts file will be deleted. See, how dangerous it could be?
To demonstrate this, let's try to execute input function again.
>>> dude = "thefourtheye"
>>> input("Enter your name: ")
Enter your name: input("Enter your name again: ")
Enter your name again: dude
Now, when input("Enter your name: ") is executed, it waits for the user input and the user input is a valid Python function invocation and so that is also invoked. That is why we are seeing Enter your name again: prompt again.
So, you are better off with raw_input function, like this
input_variable = raw_input("Enter your name: ")
If you need to convert the result to some other type, then you can use appropriate functions to convert the string returned by raw_input. For example, to read inputs as integers, use the int function, like shown in this answer.
In python 3.x, there is only one function to get user inputs and that is called input, which is equivalent to Python 2.7's raw_input.
You are running Python 2, not Python 3. For this to work in Python 2, use raw_input.
input_variable = raw_input ("Enter your name: ")
print ("your name is" + input_variable)
Since you are writing for Python 3.x, you'll want to begin your script with:
#!/usr/bin/env python3
If you use:
#!/usr/bin/env python
It will default to Python 2.x. These go on the first line of your script, if there is nothing that starts with #! (aka the shebang).
If your scripts just start with:
#! python
Then you can change it to:
#! python3
Although this shorter formatting is only recognized by a few programs, such as the launcher, so it is not the best choice.
The first two examples are much more widely used and will help ensure your code will work on any machine that has Python installed.
I also encountered this issue with a module that was supposed to be compatible for python 2.7 and 3.7
what i found to fix the issue was importing:
from six.moves import input
this fixed the usability for both interpreters
you can read more about the six library here
You should use raw_input because you are using python-2.7. When you use input() on a variable (for example: s = input('Name: ')), it will execute the command ON the Python environment without saving what you wrote on the variable (s) and create an error if what you wrote is not defined.
raw_input() will save correctly what you wrote on the variable (for example: f = raw_input('Name : ')), and it will not execute it in the Python environment without creating any possible error:
input_variable = raw_input('Enter Your Name : ')
print("Your Name Is : " + (input_variable))
input_variable = input ("Enter your name: ")
print ("your name is" + input_variable)
You have to enter input in either single or double quotes
Ex:'dude' -> correct
dude -> not correct
For python 3 and above
s = raw_input()
it will solve the problem on pycharm IDE
if you are solving on online site exactly hackerrank then use:
s = input()
We are using the following that works both python 2 and python 3
#Works in Python 2 and 3:
try: input = raw_input
except NameError: pass
print(input("Enter your name: "))
There are two ways to fix these issues,
1st is simple without code change that is
run your script by Python3,
if you still want to run on python2 then
after running your python script, when you are entering the input keep in mind
if you want to enter string then just start typing down with "input goes with double-quote" and it will work in python2.7 and
if you want to enter character then use the input with a single quote like 'your input goes here'
if you want to enter number not an issue you simply type the number
2nd way is with code changes
use the below import and run with any version of python
from six.moves import input
Use raw_input() function instead of input() function in your code with any import
sanitise your code with str() function like str(input()) and then assign to any variable
As error implies: name 'dude' is not defined
i.e. for python 'dude' become variable here and it's not having any value of python defined type assignedso only its crying like baby so if we define a 'dude' variable and assign any value and pass to it, it will work but that's not what we want as we don't know what user will enter and moreover we want to capture the user input.
Fact about these method:
input() function: This function takes the value and type of the input you enter as it is without modifying it type. raw_input()
function: This function explicitly converts the input you give into type string,
Note: The vulnerability in input() method lies in the fact that
the variable accessing the value of input can be accessed by anyone
just by using the name of variable or method.
Try using raw_input rather than input if you simply want to read strings.
print("Enter your name: ")
x = raw_input()
print("Hello, "+x)
You could either do:
x = raw_input("enter your name")
print "your name is %s " % x
or:
x = str(input("enter your name"))
print "your name is %s" % x
For anyone else that may run into this issue, turns out that even if you include #!/usr/bin/env python3 at the beginning of your script, the shebang is ignored if the file isn't executable.
To determine whether or not your file is executable:
run ./filename.py from the command line
if you get -bash: ./filename.py: Permission denied, run chmod a+x filename.py
run ./filename.py again
If you've included import sys; print(sys.version) as Kevin suggested, you'll now see that the script is being interpreted by python3
Good contributions the previous ones.
import sys; print(sys.version)
def ingreso(nombre):
print('Hi ', nombre, type(nombre))
def bienvenida(nombre):
print("Hi "+nombre+", bye ")
nombre = raw_input("Enter your name: ")
ingreso(nombre)
bienvenida(nombre)
#Works in Python 2 and 3:
try: input = raw_input
except NameError: pass
print(input("Your name: "))
Enter your name: Joe
('Hi ', 'Joe', &lttype 'str'&gt)
Hi Joe, bye
Your name: Joe
Joe
Thanks!
You can change which python you're using with your IDE, if you've already downloaded python 3.x it shouldn't be too hard to switch. But your script works fine on python 3.x, I would just change
print ("your name is" + input_variable)
to
print ("your name is", input_variable)
Because with the comma it prints with a whitespace in between your name is and whatever the user inputted. AND: if you're using 2.7 just use raw_input instead of input.
Here is an input function which is compatible with both Python 2.7 and Python 3+:
(Slightly modified answer by #Hardian) to avoid UnboundLocalError: local variable 'input' referenced before assignment error
def input_compatible(prompt=None):
try:
input_func = raw_input
except NameError:
input_func = input
return input_func(prompt)
Also here is another alternative without a try block:
def input_compatible(prompt=None):
input_func = raw_input if "raw_input" in __builtins__.__dict__ else input
return input_func(prompt)

Handling map function in python2 & python3

Recently i came across a question & confused with a possible solution,
code part is
// code part in result reader
result = map(int, input())
// consumer call
result_consumer(result)
its not about how do they work, the problem is when you are running in python2 it will raise an exception, on result fetching part, so result reader can handle the exception, but incase of python3 a map object is returned, so only consumer will be able to handle exception.
is there any solution keeping map function & handle the exception in python2 & python3
python3
>>> d = map(int, input())
1,2,3,a
>>> d
<map object at 0x7f70b11ee518>
>>>
python2
>>> d = map(int, input())
1,2,3,'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>>
the behavior of map is not the only difference between python2 and python3, input is also difference, you need to keep in mind the basic differences between the two to make code compatible for both
python 3 vs python 2
map = itertools.imap
zip = itertools.izip
filter = itertools.ifilter
range = xrange
input = raw_input
so to make code for both, you can use alternatives like list comprehension that work the same for both, and for those that don't have easy alternatives, you can make new functions and/or use conditional renames, like for example
my_input = input
try:
raw_input
except NameError: #we are in python 3
my_input = lambda msj=None: eval(input(msj))
(or with your favorite way to check which version of python is in execution)
# code part in result reader
result = [ int(x) for x in my_input() ]
# consumer call
result_consumer(result)
that way your code do the same regardless of which version of python you run it.
But as jsbueno mentioned, eval and python2's input are dangerous so use the more secure raw_input or python3's input
try:
input = raw_input
except NameError: #we are in python 3
pass
(or with your favorite way to check which version of python is in execution)
then if your plan is to provide your input as 1,2,3 add an appropriate split
# code part in result reader
result = [ int(x) for x in input().split(",") ]
# consumer call
result_consumer(result)
If you always need the exception to occur at the same place you can always force the map object to yield its results by wrapping it in a list call:
result = list(map(int, input()))
If an error occurs in Python 2 it will be during the call to map while, in Python 3, the error is going to surface during the list call.
The slight downside is that in the case of Python 2 you'll create a new list. To avoid this you could alternatively branch based on sys.version and use the list only in Python 3 but that might be too tedious for you.
I usually use my own version of map in this situations to escape any possible problem may occur and it's
def my_map(func,some_list):
done = []
for item in some_list:
done.append( func(item) )
return done
and my own version of input too
def getinput(text):
import sys
ver = sys.version[0]
if ver=="3":
return input(text)
else:
return raw_input(text)
if you are working on a big project add them to a python file and import them any time you need like what I do.

how import statement executes in python?

I read about about import statement in pydocs. It says it executes in two steps.
(1)find a module, and initialize it if necessary; (2) define a name or names in the local namespace (of the scope where the import statement occurs). The first form (without from) repeats these steps for each identifier in the list. The form with from performs step (1) once, and then performs step (2) repeatedly.
I understood some bits of it, but its still not clear to me completely.I am mainly confused about initialization step and at last it says about repeating some step.The only thing which i understood is that if we use say for example:
import sys
in this case if we use functions of this module in our script we need call them using sys.fun_name(). As the functions weren't made available locally using this importstatement.
But when we use
from sys import argv
We can simply use argv function as it makes it available local for out srcipt.
Can someone please explain me its working and also let me know my understanding is correct or not.
Even i tried to import one of the my script into another script and it gave some strange result which i know have something to do with first step of import statement,(initiallization)
##### ex17.py #####
def print_two(*args):
arg1, arg2 = args
print "arg1: %r, arg2: %r" %(arg1, arg2)
def print_two_again(arg1, arg2):
print "arg1: %r, arg2: %r" %(arg1, arg2)
def print_one(arg1):
print "arg1: %r" %arg1
def print_none():
print "I got nothing."
print_two("Gaurav","Pareek")
print_two_again("Gaurav","Pareek")
print_one("First!")
print_none()
####### ex18.py ######
import ex17
ex17.print_none()
The output which i am getting when executing ex18.py is as below
arg1: 'Gaurav', arg2: 'Pareek'
arg1: 'Gaurav', arg2: 'Pareek'
arg1: 'First!'
I got nothing.
I got nothing.
why is it like this. It should only print I got nothing once.
It prints "I got nothing." twice because the function print_none is being invoked twice. Once when loading the ex17 module (since it's imported in ex18) and once when it's called in the ex18 module. If you don't want the function calls in ex17 to execute but only the function defs to be loaded, then you may write them as follows
## in ex17.py
if __name__ == '__main__':
print_two("Gaurav","Pareek")
print_two_again("Gaurav","Pareek")
print_one("First!")
print_none()
Now this code will only be executed if it's run as a script ie. $ python ex17.py but not when it's imported into some other module. More about __main__ here
About the excerpt from the docs, it simply says how the two import forms differ. Step 1 is responsible for finding and initializing the module and step 2 for adding the names to the local namespace. So in case of,
import sys
both step 1 and 2 will be executed once. But in case of,
from sys import argv, stdout
step 1 will be executed just once, but step 2 will be executed twice as it needs to add both argv and stdout to the local namespace.