I have a task where I have to run a bunch of simulations with slightly different parameters each time. I'd like to write a Python script to automate this but I'm having an issue.
To simplify the description, I essentially have N simulations called from the command line, each with a different set of parameters, and I'd like the script to execute them one by one. Imagine that to run a simulation I would write execute_simulation... to the command line where the ... stands for the parameters of the given simulation. This is what my script looks like:
from subprocess import call
<code>
for i in range(0, N):
call('execute_simulation_%s' % ( parameters[i]))
However, I always get error messages when calling the script. Can anyone suggest why this might be the case?
It would be helpful if you had included the error messages but I'll try to help you anyway.
The call function expects a sequence of strings not a single string (although the Popen documentation states that they are converted to a string on Windows, so it may working in specific cases).
Also, in the example code you gave, you did call('execute_simulation_%s' % ( parameters[i])). If parameters[i] is not a string but a list, tuple, generator or then str will be called on that object which means you get something like execute_simulation ['arg0', 'arg1', 'arg2', 'arg3', 'arg4']. This is probably not what you want. You can call ' '.join on the sequence to get something like execute_simulation arg0 arg1 arg2 arg3 arg4.
With that being said, I assume that parameters a list of lists containing the arguments for each call. Then you could just do
args = [f'arg{i}' for i in range(5)]
parameters = [args for i in range(5)]
for args in parameters:
call(('execute_simulation', *args))
Also, consider using subprocess.run, since it is recommended to use in Python 3.5+ code (it works just like call).
I hope this works in your case.
Related
I'm currently building up a library of personal debugging functions, and wanted to make a debugging print function that would provide more quality-of-life functionality than adding print(thing) lines everywhere. My current goal is to have this pseudocode function translated to Python:
def p(*args, **kwargs)
for arg in args:
print(uneval(arg), ": ", arg)
return args
The types of **kwargs and how they'd effect the output isn't as important to this question, hence why I don't use them here.
My main problem comes from trying to have some method of uneval-ing the arguments, such that I can get the string of code that actually produced them. As a use case:
>>> p(3 + 5) + 1
3 + 5: 8 # printed by p
9 # Return value of the entire expression
There's a couple of ways that I see that I can do this, and not only am I not sure if any of them work, I'm also concerned about how Pythonic any solution that actually implements these could possibly be.
Pass the argument as a string, eval it using the previous context's local identifier dictionary (how could I get that without passing it as another argument, which I definitely don't want to do?)
Figure out which line it's being run from in the .py file to extract the uneval'd strings that way (is that even possible?)
Find some metadata magic that has the information I need already in it (if it exists, which is unlikely at best).
I am trying to create an user interface using argparse module.
One of the argument need to be converted, so I use the type keyword:
add_argument('positional', ..., type=myfunction)
and there is another optional argument:
add_argument('-s', dest='switch', ...)
in addition, I have
parsed_argument=parse_args()
However, in myfunction, I hope I can use an additional parameter to control the behavior, which is the optional argument above, i.e.
def myfunction(positional, switch=parsed_argument.switch):
...
How can I achieve that?
Simple answer: You can’t. The arguments are parsed separately, and there is no real guarantee that some order is maintained. Instead of putting your logic into the argument type, just store it as a string and do your stuff after parsing the command line:
parser.add_argument('positional')
parser.add_argument('-s', '--switch')
args = parser.parse_args()
myfunction(args.positional, switch=args.switch)
I'm not sure I did understand correctly what you want to achieve, but if what you want to do is something that looks like:
myprog.py cmd1 --switcha
myprog.py cmd2 --switchb
yes you can, you need to use subparsers. I wrote a good example of it for a little PoC I wrote to access stackoverflow's API from CLI. The whole logic is a bit long to put thoroughly here, but mainly the idea is:
create your parser using parser = argparse.ArgumentParser(...)
create the subparsers using subparsers = parser.add_subparsers(...)
add the commands with things like `subparser.add_parser('mycommand', help='Its only a command').set_defaults(func=mycmd_fn) where
mycmd_fn takes args as parameters where you have all the switches you issued to the command!
the difference from what you ask, is that you'll need one function per command, and not one function with the positional argument as first argument. But you can leverage that easily by having mycmd_fn being like: mycmd_fn = lambda *args: myfunction('mycmd', *args)
HTH
From the documentation:
type= can take any callable that takes a single string argument and returns the converted value:
Python functions like int and float are good examples of a type function should be like. int takes a string and returns a number. If it can't convert the string it raises a ValueError. Your function could do the same. argparse.ArgumentTypeError is another option. argparse isn't going to pass any optional arguments to it. Look at the code for argparse.FileType to see a more elaborate example of a custom type.
action is another place where you can customize behavior. The documentation has an example of a custom Action. Its arguments include the namespace, the object where the parser is collecting the values it will return to you. This object contains any arguments have already been set. In theory your switch value will be available there - if it occurs first.
There are many SO answers that give custom Actions.
Subparsers are another good way of customizing the handling of arguments.
Often it is better to check for the interaction of arguments after parse_args. In your case 'switch' could occur after the positional and still have effect. And argparse.Error lets you use the argparse error mechanism (e.g. displaying the usage)
I'm getting stuck with this
I have a python file which is imported from elsewhere as a module, in order to use some functions provided by it. I'm trying a way to call it form CLI, giving it 0 or 5 arguments.
def simulate(index, sourcefile, temperature_file, save=0, outfile='fig.png'):
(...)
# do calculations and spit a nice graph file.
if __name__ == '__main__':
if (len(sys.argv) == 6 ):
# ugly code alert
simulate(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])
else:
(...)
#do some other things and don't bother me
I was wondering if there's a clean way to pass all but first argument to a function.
I tried simulate(sys.argv[1:]) but it throws a single object (list), and since simulate function expects 4 arguments, it doesn't work: TypeError: 'simulate() takes at least 3 arguments (1 given)'
Tried also with simulate(itertools.chain(sys.argv[1:])) with same result.
Since this file is imported elsewhere as a module and this function is being called many times, it seems a bad idea to change the function's signature to recieve a single argument
simulate(*sys.argv[1:])
See "Unpacking Argument Lists" in the tutorial
What you want to use is called "Packing/Unpacking" in Python:
foo(*sys.argv)
See: http://en.wikibooks.org/wiki/Python_Programming/Tuples#Packing_and_Unpacking
If you want "all but first argument":
foo(*sys.argv[1:])
This is called "slicing". See: http://docs.python.org/2.3/whatsnew/section-slices.html
I have some tasks stored in db for later execution. For example i can fix task of sending email. And by cron exec task (send it). I search for best way to store code in db for later execution. For ex store it in raw string of python code and than do eval, but also i must store relative imports here..
for example for send email i must fix string like this:
s = "from django.core.mail import send_mail\n
send_mail('subj', 'body', 'email#box.ru',['email1#box.ru'], fail_silently=False)"
and later eval.. any ideas to do it best way or mb better pattern for this kind of task?
What you're doing is a bad idea mainly because you allow for way too much variability in what code will be executed. A code string can do anything, and I'm guessing there are only a few kinds of tasks you want to store for later execution.
So, figure out what the variables in those tasks are (variables in a non-programming sense: things that vary), and only store those variables, perhaps as a tuple of function arguments and a dictionary of keyword arguments to be applied to a known function.
To be even more fancy, you can have some kind of container object with a bunch of functions on it, and store the name of the function to call along with its arguments. That container could be something as simple as a module into which you import functions like Django's send_mail as in your example.
Then you can store your example call like this:
func = 'send_mail'
args = ('subj', 'body', 'email#box.ru', ['email1#box.ru'])
kwargs = {'fail_silently': False}
my_call = cPickle.dumps((func, args, kwargs))
And use it like this:
func, args, kwargs = cPickle.loads(my_call)
getattr(my_module, func)(*args, **kwargs)
Use celery for this. That's the best approach.
http://celeryproject.org/
I wouldn't use this solution at all. I would create a different handler for each task (sending a mail, deleting a file, etc). Storing code in this manner is hackish.
EDIT
An example would be creating your own format for handlers. For example each line one handler in this format:
handlername;arg1;arg2;arg3;arg4
Next you use python to read out the lines and parse them. For example this would be a stored line:
sendmail;nightcracker#nclabs.org;subject;body
Which would be parsed like this:
for line in database:
handler, *args = line.split(";")
if handler == "sendmail":
recipient, subject, body, = args[:3]
# do stuff
elif handler == "delfile":
#etc
I'd store logical commands, and exec them with something like
def run_command(cmd):
fields = map(unescape, cmd.split(";"))
handlers[fields[0]](fields[1:])
...
#handler("mail")
def mail_handler(address, template):
import whatever
...
send_mail(address, get_template(template) % user_info, ...)
this way you can have both the flexibility to add handlers without having to touching any code in the dispatcher and yet you're not writing the code details in the database that would make harder doing inspections/stats or just hot fixing jobs that didn't start yet.
To directly answer your question, eval is really only for evaluating code that will produce a result. For example:
>>> eval('1 + 1')
2
However if you simply want to execute code, possibly several lines of code, you want exec(), which by default executes inside the caller's namespace:
>>> exec("x = 5 + 5")
>>> print x
10
Note that only trusted code should be passed to either exec or eval. See also execfile to execute a file.
Having said all that, I agree with other posters that you should find a way to problematically do what you want to do instead of storing arbitrary code. You could, for example, do something like this:
def myMailCommand(...):
...
def myOtherCommand(...):
...
available_commands = {'mail': myMailCommand,
'other': myOtherCommand}
to_execute = [('mail', (arg1, arg2, arg3)),
('other', (arg1, arg2))]
for cmd, args in to_execute:
available_commands[cmd](*args)
In the above pseudo-code, I defined two methods. Then I have a dictionary mapping actions to commands. Then I go through a data structure of actions and arguments, and call the appropriate argument accordingly. You get the idea.
I'm writing a python command line program which has some interdependent options, I would like for the user to be able to enter the options in whichever order they please.
Currently I am using the getopts library to parse the command line options, unfortunately that parses them in-order. I've thrown together a system of boolean flags to leave the processing of certain command line arguments until the one they're dependent on is processed, however I had the idea of using a Priority Queue of function calls which would execute after all the command line options are parsed.
I know that Python can store functions under variable names, but that seems to call the function at the same time.
For example:
help = obj.PrintHelp()
heapq.heappush(commandQ, (0, help))
Will print the help dialog immediately. How would I go about implementing my code such that it won't call PrintHelp() immediately upon assigning it a name.
EDIT:
Oh i just realized I was pushing into a queue called help, that's my mistake.
Thanks for the tip on removing the () after PrintHelp.
What if I want to now call a function that requires more than the self argument?
myFun = obj.parseFile(path)
heapq.heappush(commandQ, (1, myFun))
Would I just make the tuple bigger and take the command line argument?
If you heappush like this:
myFun = obj.parseFile
heapq.heappush(commandQ, (1, myFun, path))
then to later call the function, you could do this:
while commandQ:
x=heapq.heappop(commandQ)
func=x[1]
args=x[2:]
func(*args)
Use
help = obj.PrintHelp
without the parentheses. This makes help reference the function.
Later, you can call the function with help().
Note also (if I understand your situation correctly), you could just use the optparse or (if you have Python2.7 or better) argparse modules in the standard library to handle the command-line options in any order.
PS. help is a built-in function in Python. Naming a variable help overrides the built-in, making it difficult (though not impossible) to access the built-in. Generally, it's a good idea not to overwrite the names of built-ins.
Instead of using getopts, I would suggest using optparse (argparse, if you are using a newer python version): most probably, you will get everything you need, already implemented.
That said, in your example code, you are actually calling the function, while you should simply get its name:
help = obj.PrintHelp
heapq.heappush(help, (0, help))
If you want to store a complete function call in Python, you can do it one of two ways:
# option 1: hold the parameters separately
# I've also skipped saving the function in a 'help' variable'
heapq.heappush(commandQ, (0, obj.PrintHelp, param1, param2))
# later:
command = commandQ[0]
heapq.heappop(commandQ)
command[1](*command[2:]) # call the function (second item) with args (remainder of items)
Alternatively, you can use a helper to package the arguments up via lambda:
# option 2: build a no-argument anonymous function that knows what arguments
# to give the real one
# module scope
def makeCall(func, *args):
return lambda: func(*args)
# now you can:
help = makeCall(obj.PrintHelp, param1, param2)
heapq.heappush(commandQ, (0, help))
If you need keyword arguments, let me know and I'll edit to take care of those too.