Is there a way to make a program which executes other programs?
I was creating a project for school then I had an idea of creating a main program which will run different program according to my choice.
I am using VS code and I created 2 programs in same folder(Here is the screenshot in case you are confused):
Here as you can see I have 2 programs(one is rockpaper.py and other is pass.py) inside of a folder named (ROCKPAPER) is there a way I can run both of these program by making another program inside of this same folder(ROCKPAPER)????
Is there a module for this?
The best practice is to import the two programs in a 3rd one like
import pass
import rockpaper
which will execute those codes.
No module is needed, this is basic functionality and you can simply import your sub-scripts into the main script.
import rockpaper
import pass
to run them, simply write
rockpaper
pass
rock.py
def stone():
return ('This is rock')
paper.py
Note here I have imported rock and assigned rock's result to a variable
import rock
def papyrus():
return ("This is paper")
scissors.py
Note here, I got rock and paper imported and their return values are being printed from this file.
import rock
import paper
def sharp():
rocke = rock.stone()
papery = paper.papyrus()
print(f"{rocke} {papery} But I am a scissors")
if __name__ == "__main__":
sharp()
Output:
This is rock This is paper But I am a scissors
Process finished with exit code 0
You should really be studying these basics though.
Here's a short "driver" program you can put in the same folder as the others. What it does is create a menu of all the other Python script files it finds in the same folder as itself and asks the user to pick one to run. If the user enters number of one of those listed, it then runs that script and quits (otherwise it repeats the question).
It uses the subprocess module to execute the chosen script.
from pathlib import Path
import subprocess
import sys
filepath = Path(__file__)
current_folder = filepath.parent
this_script = filepath.name
print(f'{this_script=}')
print(f'{current_folder=}')
scripts = sorted(script for script in current_folder.glob('*.py') if script != filepath)
menu = [script.stem for script in scripts]
print('Available programs:')
for i, script in enumerate(menu, start=1):
print(f' {i:2d}. {script}')
while True:
choice = input('Which program would you like to run (or 0 to quit)? ')
try:
choice = int(choice)
except ValueError:
print("Sorry, did not understand that.")
continue
if choice in range(len(menu)+1):
break
else:
print("Sorry, that is not a valid response.")
continue
if choice:
print(f'Running program {menu[choice-1]}')
subprocess.run([sys.executable, f'{scripts[choice-1]}'])
It's actually pretty simple!
import os
os.system("python anotherProgram.py")
Essentially, you're giving it a shell command.
Related
I'm making a car parking system and I have some problems.
So the main thing is that I have 3 different py files, and all of them have different functions. For example I use Programa.py to ask users what they would like to do and some other functions. I use GETDATA.py to get rows from PostgreSQL server and then to pay for the parking charges.
And last of all I have REGISTRATION.py to Register car numbers to parking and insert them to SQL Database.
So the main problem is that after the "What would you like to do?" menu from Programa.py I use if statement, which imports other .py files to make their job done. Here's the code of If statement in Programa.py:
while Pasirinkimas:
try:
Registration_Or_Pay = int(input("~ What would you like to do?\n1.Register a car\n2.Pay for parking\n"))
if int(Registration_Or_Pay == 1):
import REGISTRATION
break
elif int(Registration_Or_Pay == 2):
import GETDATA
break
except ValueError:
print("NOT A NUMBER!")
After imported GETDATA.py Let's say I paid for parking and now I have to return to Programa.py to keep the program running and performing other parking operations as number registrations again.
And the problem is that after importing the Programa.py from GETDATA.py It launches, but after picking a number, to register a number program closes.
This is some lines of GETDATA.py file which I imported from main system .py file, which is called "Programa", you can see it at the end I'm trying to import it again to always keep the program running and to return to main script which asks what you would like to do.
finally:
#closing database connection.
if(connection):
cursor.close()
connection.close()
print("PostgreSQL connection is closed")
with open (Logs, mode='a',encoding='utf-8') as logwrite:
Time = datetime.datetime.now()
logwrite.writelines("\n {} Record SELECTED SUCCESSFULLY FROM Vartotojai DB. CARNUM {} REG_TIME: {} PARKING TIME: {} PRICE : {} STATUS : {}".format(Time.strftime("%Y-%m-%d %H:%M:%S"), car_numb, Laikas_ISDB, total_hours, total_charges, Time ))
logwrite.close()
time.sleep(2) # 2MINUTES 2 PAY.
os.system('cls')
import Programa # Return to program
I was talking with my friend who is good at python, he mentioned that I shouldn't use imports like this, because the import runs once in runtime. only first import directive takes effect. So my question would be How should I switch between these functions?
The last word in your question is actually what you should google for :).
Read something about functions. You put the code of the files you want to import into functions. Then you import all files you need at the beginning of your script and when you want to run the code you call the function its in.
Say you want to ask the user something from the terminal at the end of your program.
However, during the program run, the user pressed the enter key.
import sys
import time
print("Hit enter now to see this 'problem'")
time.sleep(1)
# Hit enter now while the program sleeps!
a=input("Do you want to delete something that is really bad to delete? [Y|n]")
if a.lower()!="n":
print("\nNO! YOU DELETED IT!")
Of course, it's stupid to delete stuff with default response, and I don't do that. However, It's annoying that I, the user, sometimes hit enter and the default is what goes.
I'm actually using click to read the input. So I'd want a preventative command before click executes;
import sys
import click
import time
print("Hit enter now to see this 'problem'")
time.sleep(1)
# Hit enter now while the program sleeps!
# Clear stdin here somehow.
sys.stdin.flush() # <- doesn't work though
a=input("Do you want to delete something that is really bad to delete? [Y|n]")
if a.lower()!="n":
print("\nNO! YOU DELETED IT!")
I'm on Linux (Ubuntu 16.04 and Mac OS).
Any ideas?
Turns out I needed termios.tcflush() and termios.TCIFLUSH which does exactly what is asked:
import sys
from termios import tcflush, TCIFLUSH
import click
import time
print("Hit enter now to see this 'problem'")
time.sleep(1)# Hit enter while it sleeps!
tcflush(sys.stdin, TCIFLUSH)
# Discards queued data on file descriptor 'stdin'.
# TCIFLUSH specifies that it's only the input queue.
# Use TCIOFLUSH if you also want to discard output queue.
a=input("Do you want to delete something that is really bad to delete? [Y|n]")
if a.lower()!="n":
print("\nNO! YOU DELETED IT!")
else:
print("Phew. It's not deleted!")
Good Afternoon,
I used a version of this method to map a dozen drive letters:
# Drive letter: M
# Shared drive path: \\shared\folder
# Username: user123
# Password: password
import subprocess
# Disconnect anything on M
subprocess.call(r'net use * /del', shell=True)
# Connect to shared drive, use drive letter M
subprocess.call(r'net use m: \\shared\folder /user:user123 password', shell=True)
The above code works great as long as I do not have a folder with a file in use by a program.
If I run the same command just in a cmd window and a file is in use when I try to disconnect the drive it returns the Are you sure? Y/N.
How can I pass this question back to the user via the Py script (or if nothing else, force the disconnect so that the code can continue to run?
To force disconnecting try it with /yes like so
subprocess.call(r'net use * /del /yes', shell=True)
In order to 'redirect' the question to the user you have (at least) 2 possible approaches:
Read and write to the standard input / output stream of the sub process
Work with exit codes and start the sub process a second time if necessary
The first approach is very fragile as you have to read the standard output and interpret it which is specific to your current locale as well as answering later the question which is also specific to your current locale (e.g. confirming would be done with 'Y' in English but with 'J' in German etc.)
The second approach is more stable as it relies on more or less static return codes. I did a quick test and in case of cancelling the question the return code is 2; in case of success of course just 0. So with the following code you should be able to handle the question and act on user input:
import subprocess
exitcode = subprocess.call(r'net use * /del /no', shell=True)
if exitcode == 2:
choice = input("Probably something bad happens ... still continue? (Y/N)")
if choice == "Y":
subprocess.call(r'net use * /del /yes', shell=True)
else:
print("Cancelled")
else:
print("Worked on first try")
How do I get main to run again without executing the whole script again?
import sys #importing module that is used to exit the script
def main ():
#doing stuff
main ()
#Re-run the script - looking for a cleaner way to do this!
def restart ():
restart = input("Press any key + Enter to start again, or x + Enter to exit.")
if(restart != "x"):
exec(open("./calc.py").read())
# not sure how to run main() again without calling out the script name again?
else:
print ("Exiting!")
sys.exit ((main))
restart ()
#End of Program
You can re-run the main module-method as many times as you want by directly calling main() sequentially:
def main( ):
# Code goes here...
return;
main();
main();
main();
However, if you want the user-interaction like your restart method has, you might want to consider defining main with an optional parameter (one that has a default value) that controls whether you ask to re-run the method or not.
def main( argv, AskRestart= True ):
# Main code goes here....
if ( AskRestart ):
# User interaction code goes here ...
return;
Also, you can look into the atexit package in Python 3.5.1 to see how you can assign a method to be run only when exiting the interpreter:
https://docs.python.org/3.5/library/atexit.html
That would allow you to do whatever you want and then when everything is done, give someone the option of restarting the entire module. This would remove the reliance on the exec call, and be a more coherent and simpler approach to getting the exact same expected functionality.
In addition to Tommy's great advice, (I'm not sure of your goal in continually restarting main() as main is an empty function that doesn't do anything yet, but..) one way to have main continually repeat until the user enters x may be to use a while True loop:
import sys #importing module that is used to exit the script
def main ():
#doing stuff
restart() # <-- use main to restart()
#Re-run the script - looking for a cleaner way to do this!
def restart ():
restart = raw_input("Press any key + Enter to start again, or x + Enter to exit.")
while True: # <-- key to continually restart main() function
if(restart != "x"):
exec(open("./calc.py").read())
# not sure how to run main() again without calling out the script name again?
main() # <-- restart main
else:
print ("Exiting!")
sys.exit ((main))
restart ()
#End of Program
Hope this also helps!
I am fairly new to Python and currently learning to work with functions and multiple modules within a python program.
I have two modules "Functions_Practice_Main" (which runs a menu) and "Functions_Practice" which has the code for a simple program that works out if a user's input divides by 7 or not (I know...pretty dull practice).
What I want to do is get the user to enter their name when the menu module is runs and then get this global variable to by displayed througout the program to make the program more personal.
However, when I run the menu module it asks for a name twice. The first name entered is displayed in the 'divide by 7' program and the second name entered is displayed in the menu. I understand why this is happening (due to the import of the Functions_Practice module demanding to know what the global variables are in the Functions_Practice_Main module before the rest of the code has a chance to run) BUT I REALLY NEED TO KNOW HOW TO FIX THIS.
How can I get the user to enter their name ONCE when the menu module is runs and then get this global variable to by displayed througout the program to make it more personal for the user.
Functions_Practice_Main
import Functions_Practice, sys
name = input("What is your name? ")
def main():
while True:
print(name, "'s Menu")
print("*******************")
print("1. Can you divide by 7?")
print("2. Quit")
print("*******************")
selection = int(input("Your number selection please..."))
if selection == 1:
Functions_Practice.main()
elif selection == 2:
sys.exit()
else:
print("Your number selection was invalid, please try again...")
if __name__ == '__main__':
main()
*Functions_Practice*
import Functions_Practice_Main
def inputData(name):
print(name)
number = int(input(" Please enter your number: "))
return number
def processData(number):
answer = number % 7
if answer == 0:
remainder = True
else:
remainder = False
return remainder
def outputData(remainder):
if remainder == True:
print("The number you entered doesn't have a remainder")
elif remainder == False:
print("The number you entered does have a remainder")
def main():
number = inputData(Functions_Practice_Main.name)
remainder = processData(number)
outputData(remainder)
if __name__ == '__main__':
main()
Running a module as a script does not count as importing it as a module. When the Functions_Practice_Main.py script imports Functions_Practice, and Functions_Practice imports Functions_Practice_Main, Python doesn't care that the code in Functions_Practice_Main.py is already running as the main script. Python will run it again to produce the module.
How do you fix this? Well, there are several things you should do. First, avoid circular imports if at all possible. Instead of having Functions_Practice import Functions_Practice_Main, pass any data Functions_Practice needs from Functions_Practice_Main as function arguments.
In Functions_Practice_Main:
Functions_Practice.interactive_remainder_test(name)
In Functions_Practice:
def interactive_remainder_test(name):
number = inputData(name)
remainder = processData(number)
outputData(remainder)
Second, things like this:
name = input("What is your name? ")
belong in a file's main, since they shouldn't run when a file is imported.