import sys
import pathlib
import os
def GetAndSplitCommand(line, file):
if line is 1:
line = 0
f=open(file)
lines=f.readlines()
unsplit=lines[line]
split=unsplit.split()
return split
def ExecuteCode(*args):
lists = [item for item in args]
print(lists)
parameters = args
if lists[0] == "hi":
HelloWorld()
return
elif lists[0] == "bye":
GoodbyeWorld()
return
def HelloWorld():
print(" Hello World!")
return
def GoodbyeWorld():
print(" Bye World!")
return
command = GetAndSplitCommand(1, "food.txt")
ExecuteCode(command)
In food.txt I have the word "hi", so, with this code it should print out "Hello World!", however it simply prints out [['hi']]. I have tried many times to reformat the code and I need advice as to what I need to do.
Also, its not a indentation issue, stackoverflow just isn't nice with my code.
Another note, this program is essentially meant to read the line of a file, split the line into separate "parameters", and using the ExecuteCode() function, do something ifthe first parameter is X.
It looks to me like you've misunderstood what *args does in a function declaration.
When you write def ExecuteCode(*args):, you're staying that you want to allow ExecuteCode to be called with a variable number of arguments. For instance, other code could call ExecuteCode("foo", "bar", "baz") (three arguments) or ExecuteCode() (zero arguments). The args variable in the function will be a list of those argument values (so ["foo", "bar", "baz"] or [] for my two example calls).
In your code, you're calling the function with one argument ExecuteCode(command). If command is the list ['hi'], then inside ExecuteCode, args will be [['hi']], since it always puts the arguments in a list, since there might be several of them.
You probably don't need to use *args here. Instead, just use:
def ExecuteCode(lists):
if lists[0] == "hi":
...
Note that there are a few other style issues with your code (that won't prevent it from running, but do make it more complicated or confusing that it needs to be). One issue is naming. A common Python convention is to use lowercase_names_with_underscores for most functions, and reserve CapitalizedNames for classes. Another issue is picking names that are clear about what they do. The lists variable in ExecuteCode is an example of this. In your current buggy code it's a list of lists, so that name might make some sense (if that was what you wanted), but if you change it as I suggest above to be a list of strings, you should rename it something else, since it's no longer a list of lists.
Related
I'm trying to store a function in a list, retrieve the function from the list later, and then call on that function. This is basically what I want to do, without any specifics. It doesn't show my purpose, but it's the same issue.
elements: list = [] # List meant to contain a tuple with the name of the item and the function of the item.
def quit_code():
exit()
element.append(("quit", quit_code))
Now, somewhere else in the code, I want to be able to use an if statement to check the name of the item and, if it's the right one at that time, run the function.
user_input = "quit" # For brevity, I'm just writing this. Let's just imagine the user actually typed this.
if elements[0][0] == user_input:
#This is the part I don't understand so I'm just going to make up some syntax.
run_method(elements[0][1])
The method run_method that I arbitrarily made is the issue. I need a way to run the method returned by elements[0][1], which is the quit_code method. I don't need an alternative solution to this example because I just made it up to display what I want to do. If I have a function or object that contains a function, how can I run that function.
(In the most simplified way I can word it) If I have object_a (for me it's a tuple) that contains str_1 and fun_b, how can I run fun_b from the object.
To expand on this a little more, the reason I can't just directly call the function is because in my program, the function gets put into the tuple via user input and is created locally and then stored in the tuple.
__list_of_stuff: list = []
def add_to_list(name, function):
__list_of_stuff.append((name, function))
And then somewhere else
def example_init_method():
def stop_code():
exit()
add_to_list("QUIT", stop_code())
Now notice that I can't access the stop_code method anywhere else in the code unless I use it through the __list_of_stuff object.
Finally, It would be nice to not have to make a function for the input. By this, I mean directly inserting code into the parameter without creating a local function like stop_code. I don't know how to do this though.
Python treats functions as first-class citizens. As such, you can do things like:
def some_function():
# do something
pass
x = some_function
x()
Since you are storing functions and binding each function with a word (key), the best approach would be a dictionary. Your example could be like this:
def quit_code():
exit()
operations = dict(quit=quit_code)
operations['quit']()
A dictionary relates a value with a key. The only rule is the key must be immutable. That means numbers, strings, tuples and other immutable objects.
To create a dictionary, you can use { and }. And to get a value by its key, use [ and ]:
my_dictionary = { 'a' : 1, 'b' : 10 }
print(my_dictionary['a']) # It will print 1
You can also create a dictionary with dict, like so:
my_dictionary = dict(a=1, b=10)
However this only works for string keys.
But considering you are using quit_code to encapsulate the exit call, why not using exit directly?
operations = dict(quit=exit)
operations['quit']()
If dictionaries aren't an option, you could still use lists and tuples:
operations = [('quit',exit)]
for key, fun in operations:
if key == 'quit':
fun()
I would like to call a function from a user input, but include arguments in the parenthesis. For example, if I have a function that takes one argument:
def var(value):
print(value)
I would like to ask the user for a command and arguments, then call the function with the arguments:
Input Command: var("Test")
Test
Split the function name from the arguments. Look up the function by name using a predefined map. Parse the arguments with literal_eval. Call the function with the arguments.
available = {}
def register_func(f):
available[f.__name__] = f
#register_func
def var(value):
print(value)
from ast import literal_eval
def do_user_func(user_input):
name, args = user_input.split('(', 1)
return available[name](*literal_eval('(' + args[:-1] + ',)'))
do_user_func("var('test')") # prints "test"
This is still incredibly brittle, any invalid input will fail (such as forgetting parentheses, or an invalid function name). It's up to you to make this more robust.
literal_eval is still somewhat unsafe on untrusted input, as it's possible to construct small strings that evaluate to large amounts of memory. '[' * 10 + ']' * 10, for a safe but demonstrative example.
Finally, do not use eval on untrusted user input. There is no practical way to secure it from malicious input. While it will evaluate the nice input you expect, it will also evaluate code that, for example, will delete all your files.
Any attempt to make eval safe will end up being more complex than any of the solutions here, for no practical benefit. It will still not be safe in some way you didn't anticipate. Don't do it.
I am going to post this solution as an alternative, under the assumption that you are dealing with simple inputs such as:
var(arg)
Or, a single function call that can take a list of positional arguments.
By using eval it would be a horrible un-recommended idea, as already mentioned. I think that is the security risk you were reading about.
The ideal way to perform this approach is to have a dictionary, mapping the string to the method you want to execute.
Furthermore, you can consider an alternative way to do this. Have a space separated input to know how to call your function with arguments. Consider an input like this:
"var arg1 arg2"
So when you input that:
call = input().split()
You will now have:
['var', 'arg1', 'arg2']
You can now consider your first argument the function, and everything else the arguments you are passing to the function. So, as a functional example:
def var(some_arg, other_arg):
print(some_arg)
print(other_arg)
d = {"var": var}
call = input().split()
d[call[0]](*call[1:])
Demo:
var foo bar
foo
bar
You should investigate the cmd module. This allows you to parse input similar to shell commands, but I believe you can get tricky and change the delimiters if the parentheses are an important part of the specification.
Instead of using eval, you can parse it yourself. This way, you have control over how each function should parse/deserialize the user input's arguments.
import sys, re
def custom_print(value):
print value
def custom_add(addends):
print sum(addends)
def deserialize_print(args):
# just print it as is
custom_print(args)
def deserialize_add(args):
# remove all whitespace, split on commas, parse as floats
addends = [float(x) for x in re.sub(r"\s", "", args).split(",")]
# send to custom_add function
custom_add(addends)
def get_command():
cmd_input = raw_input("Command: ")
# -- check that the command is formatted properly
# and capture command groups
match = re.match(r"^([a-zA-Z0-9]+)(\(.*\))?$", cmd_input)
if match:
# extract matched groups to separate variables
(cmd, argstring) = match.groups()
# strip parenthesis off of argstring
if argstring:
args = argstring[1:-1]
# send the whole argument string to its corresponding function
if cmd == "print":
deserialize_print(args)
elif cmd == "add":
deserialize_add(args)
elif cmd == "exit":
sys.exit()
else:
print "Command doesn't exist."
else:
print "Invalid command."
# recurse until exit
get_command()
# -- begin fetching commands
get_command()
This is a pretty rough setup, although you can get by with some more error checking and improving the deserializing functions and modularizing function additions.
If the decoupled deserialize functions seem too much, you can also just move the deserialization into the custom functions themselves.
Following is an example of function called from user-input, using Class:
class Wash:
def __init__(self, amount):
self.amount = amount
if amount == 12:
print("Platinum Wash")
elif amount == 6:
print("Basic Wash")
else:
print("Sorry!")
amount = int(input("Enter amount: "))
payment = Wash(amount)
I am trying to make a function's output behave as if it's my input. The goal is to make a new output from the old output.
I have some code that looks like this:
def func():
BLOCK OF CODE
func()
There is no return statement in the function and no parameters within the parenthesis.
When I type func() to call my function as shown above, I get the desired output, which is a bunch of printed statements. Now I want to do something with that output to get another output.
All I'm trying to do is effectively "pipe" the output of one function into the input of another function (or, if possible, not even worry about creating another function at all, and instead doing something more direct). I looked into Python 3 writing to a pipe
but it did not help me. I also tried defining another function and using the preceding function as a parameter, which did not work either:
def another_func(func):
print another_statement
another_func(func)
I also tried making a closure (which "kind" of worked because at least it printed the same thing that func() would print, but still not very encouraging):
def func():
def another_func():
print another_statement
BLOCK OF CODE
another_func()
Finally, I tried designing both a decorator and a nested function to accomplish this, but I have no parameters in my function, which really threw off my code (didn't print anything at all).
Any advice on how to manipulate a function's output like as if it is your input so that it's possible to create a new output?
You could achieve this by redirecting stdout using a decorator:
from StringIO import StringIO
import sys
def pipe(f):
def decorated(*args, **kwargs):
old,sys.stdout = sys.stdout,StringIO()
try:
result = f(*args, **kwargs)
output = sys.stdout.getvalue()
finally:
sys.stdout = old
return result, output
return decorated
You could then get the result, output pair from any decorated function, eg:
#pipe
def test(x):
print x
return 0
test(3) -> (0, '3\n')
However, I can't think of a good reason why you'd want to do this.
(Actually, that's not quite true; it is handy when writing unit tests for user IO, such as when testing student assignments in a software engineering course. I seriously doubt that that's what the OP is trying to do, though.)
Return the desired value(s) from the function - instead of printing the values on the console, return them as strings, numbers, lists or any other type that makes sense. Otherwise, how do you expect to "connect" the output of a function as the input to another, if there is no output to begin with?
Of course, printing on the console doesn't count as output unless you're planning to eventually use OS pipes or a similar mechanism to connect two programs on the console, but keep things simple! just use the function's return values and worry about pipes later if and only if that's necessary for your problem in particular.
After reading the comments: "connecting" two functions by printing on the console from one and reading from the console from the other would be a really bad idea in this case, first you have to grasp the way functions return values to each other, trust me on this one: you have to rethink your program! even though other answers (strictly speaking) answer your original question, that's absolutely not what you should do.
just for fun ... because OP asked for it
import StringIO
import sys
def func1():
for i in range(1,10):
print "some stuff %d"%i
def func2(func):
old_std = sys.stdout
sys.stdout = StringIO.StringIO()
try:
func()
return sys.stdout.getvalue().splitlines()
finally:
sys.stdout = old_std
print func2(func1)
You need to return a value from your function. This can be used to assign the value into another variable.
Say I define some function doubleThis that will double the input
def doubleThis(x):
print 'this is x :', x
return x * 2 # note the return keyword
Now I can call the function with 3, and it returns 6 as expected
>>> doubleThis(3)
this is x : 3
6
Now I have another function subtractOne that returns the input value, minus 1.
def subtractOne(i):
print 'this is i :', i
return i - 1
Now comes the answer to your question. Note that we can call the first function as the input to the second, due to the fact that it has a return value.
>>> subtractOne(doubleThis(3))
this is x : 3
this is i : 6
5
I'm currently working on an experiment where I'm implementing an interpreter for an old in-game scripting language. It's a forth based language, so I figure it would be fairly easy to just have the instructions (once verified and santized) put into a big list.
Once I've got the code in a list, I am trying to iterate through the entire program in a for loop that processes the instructions one at a time. Certain items, like strings, could be placed onto a variable that holds the current stack, which is easy enough. But where I'm stuck is making commands happen.
I have a big list of functions that are valid and I'd like it to where if any instruction matches them, it calls the associated function.
So, for example, if I had:
"Hello, world!" notify
...the code would check for notify in a list and then execute the notify function. The bottom line is: How do I translate a string into a function name?
You could keep a dictionary of functions the code can call, and then do a look up when you need to:
def notify(s):
print(s)
d = {"notify": notify}
d["notify"]("Hello, world!")
You can do it through locals which is a dictionary with th current local symbol table:
locals()["notify"]()
or though globals which returns a dictionary with the symbol table of globals:
globals()["notify"]()
You can give arguments too e.g.:
locals()["notify"]("Hello, world!")
or
globals()["notify"]("Hello, world!")
If you have a dict called commands that maps names to functions, you can do it like this:
def my_notify_function():
print(stack.pop)
commands = {'notify': my_notify_function, ...}
for item in program:
if item in commands:
commands[item]()
else:
stack.push(item)
Something like:
import re
class LangLib(object):
pattern = re.compile(r'"(.*?)" (.*)')
def run_line(self, line):
arg, command = re.match(LangLib.pattern, line).groups()
return getattr(self, command)(arg)
def notify(self, arg):
print arg
Then your engine code would be:
parser = LangLib()
for line in program_lines:
parser.run_line(line)
Create a dictionary of function names and some tags.
I have tried it several times before, it works really well.
Is there a way to pass a list as a function argument to eval() Or do I have to convert it to a string and then parse it as a list in the function?
My simple example looks like:
eval("func1(\'" + fArgs + "\')")
I'm just not sure if there is a better way of taking fArgs as a list instead of a string
Note:
The list is provided from a JSON response
EDIT: Ok here's a bit more of my class so there's a better understanding of how I'm using eval
def test(arg):
print arg
#Add all allowed functions to this list to be mapped to a dictionary
safe_list = ['test']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
class Validate:
def __init__(self, Value, fName, fArgs):
eval(fName + "(\'" + fArgs + "\')", {"__builtins__":None},safe_dict)
I may be wrong in thinking this, but to my understanding this is a safe use of eval because the only functions that can be called are the ones that are listed in the safe_list dictionary. The function to be run and the arguments for that function are being extracted out of a JSON object. The arguments are to be structured as a list, Will joining the list together with ", " be interpreted as actual arguments or just a single argument?
If you're using Python 2.6.x, then you should be able to use the json module (see py doc 19.2). If not, then there is python-json available through the python package index. Both of these packages will provide a reader for parsing JSON data into an appropriate Python data type.
For your second problem of calling a function determined by a message, you can do the following:
def foo():
print 'I am foo!'
def bar():
pass
def baz():
pass
funcs = {'func_a':foo, 'func_b':bar, 'func_c':baz}
funcs['func_a']()
This approach can be a bit more secure than eval because it prevents 'unsafe' python library functions from being injected into the JSON. However, you still need to be cautious that the data supplied to your functions can't be manipulated to cause problems.
Specifying parameters the following way works:
root#parrot$ more test.py
def func1(*args):
for i in args:
print i
l = [1,'a',9.1]
func1(*l)
root#parrot$ python test.py
1
a
9.1
so, no direct need for eval(), unless I'm misunderstanding something.
Using a library to parse JSON input may be a better approach than eval, something like:
import json
func1(json.loads(fArgs))
Assert-ing that user input is correct would be a good idea, too.
The others have a good point, that you shouldn't be using eval. But, if you must:
eval("func1(%s)" % ", ".join(fArgs))
will call the function with all the arguments in the list. This:
eval("func1([%s])" % ", ".join(fArgs))
will call it with the list of arguments in just one argument. Maybe you even want this?
eval("func1([%s])" % ", ".join(map(eval, fArgs)))
which would eval the arguments as well?