Home > Software engineering >  Run multiple scripts in Python with conditions
Run multiple scripts in Python with conditions

Time:03-11

I have several scripts, let's say first.py, second.py, ..., last.py (with hundreds lines of code) and I want to run them in order and stop the process if any of them fails. Once all have been executed I have to re-execute first.py after 30 min after the last.py execution.

I'm a beginner in Python, so my idea is to create a .bat file that runs a global.py script which calls all this scripts. So the only thing I would have to do is double click the .bat file. Of course, I am not sure at all that this is the best way.

I have already done this and tested with some simple examples but I would like to know if there is a better way to do it.

My .bat file is something like

python ".\global.py"
pause

And my global.py is something like

import datetime,time

scripts = ["first.py","second.py"] # better something like listing ".py" files with glob()

try:
    for s in scripts:
        exec(open(s).read())
        print(f"{s} executed at {datetime.datetime.now().time()}")

    # Wait 30 min
    time.sleep(1800)

    exec(open(scripts[0]).read())
    print(f"{scripts[0]} re-executed at {datetime.datetime.now().time()}")

except BaseException as e:
    print("Error:")
    print(e)

Is that right? I heard that using "exec" is not highly recommended. Other option would be define all scritps as functions, like

def function_first():
   #first.py script content

if __name__ == "__main__":
   function_first()

And use "import" instead in the global.py. I mean:

from datetime import datetime
from time import sleep
from first import function_first
from second import function_second

try:
    function_first()
    print(f"first.py executed at {datetime.now().time()}")
except BaseException as e:
    print("Error in first.py:")
    print(e)
    raise

try:
    function_second()
    print(f"second.py executed at {datetime.now().time()}")
except BaseException as e:
    print("Error in second.py:")
    print(e)
    raise

#Wait 30 min
sleep(1800)

function_first()
print(f"{scripts[0]} re-executed at {datetime.datetime.now().time()}")


But:

  • Can I import and call functions by its name in a for loop?
  • Is it really worth it (or does it make sense) modify all scripts (with tones of code) to "convert" them into functions?
  • With the try-exception that I wrote, if a script failed would I get the error?

I'm using Python 3 in Windows 10. Thanks!

CodePudding user response:

I don't have access to python3 to test this right now, but it looks like you can do all of this from python3!

Your main python script, do a from subprocess import check_output.

Then you can use check_output in a loop to call your other python scripts:

check_output(f"python {yourScriptPathVariable}", shell=True).decode()

This will return whatever your python scripts output. Ideally, these scripts would output either a 0 for success, or something else for a failure, so you can easily break out of the loop you're in.

Rerunning the script half an our later could easily be handled by a batch file.

CodePudding user response:

To answer your questions:

Is that right? I heard that using "exec" is not highly recommended.

exec is just bad practice, it makes your code unreadable and unpredictable.

Can I import and call functions by its name in a for loop?

Yes, that is the best was to do what you want.

Is it really worth it (or does it make sense) modify all scripts (with tones of code) to "convert" them into functions?

Depends, but if all of your scripts can just be run with python script.py and no-arguments, then importing and running may not require you to modify any of them.

If your scripts don't have a if __name__ == "__main__": block, then all of their code will run on import, so you would have to replace your exec() call with an __import__() (import expects a module name, so no .py at the end).

This is also a bad solution, you should really restructure you code to import functions and then call them in global.py. If you intend to reuse or modify these scripts in the future - it's worth your time to refactor everything.

With the try-exception that I wrote, if a script failed would I get the error?

Yes, your try-except would catch any exception encountered while execution one of your scripts.

This is how you should ideally do it:

from script1 import function1
from script2 import function2
...
from scriptn import functionn

scripts = [function1, function2, ..., functionn]
try:
    for func in scripts :
        func()
    time.sleep(1800)
    function1()
    print(f"{function1} re-executed at {datetime.datetime.now().time()}")
except Exception as e:
    print("Error:")
    print(e)

  • Related