Executing Python Files From Another (cont.)
Question:
I’ve written a question about this project I’m working on already (see Executing a python file from another for my project’s structure), but I’ve encountered a new issue. In the previous question, the tip I was given was to either use import statements or subprocesses. When I tried imports, I was able to navigate to each file one time only. Per the answer given to me, I next tried to use subprocesses so I could use each file multiple times. This is the current iteration of my code that I am using. Note that all of my programs are meant to be interactive in the python terminal.
import subprocess
f = open("readme_files/index.txt")
p = open("readme_files/projects.txt")
print(f.read())
func = 0
while True:
func = int(input("Requested Operation: "))
if func == 0:
print(p.read())
elif func == 1:
subprocess.run("projects/dice_app.py")
break
elif func == 2:
subprocess.run("projects/text_to_math.py")
break
else:
req_op = ''
print("Invalid operation. Please try again.")
I don’t really understand how these subprocesses work and the tip I was given didn’t work, returning this set of errors. Note I am using MS VScode with the Python 3.10.6 SDK:
File "[my user directory]Python Projectsstart_here.py", line 14, in <module>
subprocess.run("projects/dice_app.py")
File "C:Program FilesPython310libsubprocess.py", line 501, in run
with Popen(*popenargs, **kwargs) as process:
File "C:Program FilesPython310libsubprocess.py", line 969, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:Program FilesPython310libsubprocess.py", line 1438, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
OSError: [WinError 193] %1 is not a valid Win32 application
I don’t really understand what any of this means, so any help is much appreciated.
Answers:
Likely, the reason you can only use the imports once is that the imported Python scripts do not contain methods but runnable code. Therefore, adjust your imported Python scripts into defined methods. Then, you can import whole script or specific underlying methods to be called as many times as needed in top level script.
Additionally, consider reading all text files in context managers to ensure they close properly. Be careful you are not reading large amounts of text with read()
, otherwise loop across lines. Even encapusulate text reads in functions and call as needed. Finally, consider a dictionary and avoid the the multiple if
/elif
conditions.
from projects.dice_app import my_dice_app_func
from projects.text_to_math.py import my_text_to_math_func
def print_index():
with open("readme_files/index.txt") as f:
print(f.read())
def print_projects():
with open("readme_files/projects.txt") as p:
print(p.read())
return 0
def invalid_input():
print("Invalid operation. Please try again.")
return ''
print_index()
func_dict = {
0 = print_projects,
1 = my_dice_app_func,
2 = my_text_to_math_func
}
func = 0
while True:
func = int(input("Requested Operation: "))
req_func = func_dict.get(func, invalid_input)
req_op = req_func()
if not req_op in [0, '']:
break
Subprocesses are not a proper solution for your problem. You said your imports didn’t work (only executed once) – that’s because you used them wrong. Imports are not supposed to be used as a standard piece of code. When you import something, all of the top-level code is executed in order to define the variables. On any further import of the same script, those variables are simply reused, that’s why it is not executed again.
First, make sure your imports have no side effects. All of the top-level code should be moved into a function, e.g. main()
. Then you can use very common clause if __name__=="__main__":
to make sure this function will not be executed on import.
So, let’s say your script contains the following:
i = 10
x = 12
print(i / x)
In order to make it work properly with imports, change it to something like that:
def main():
i = 10
x = 12
print(i / x)
if __name__ == "__main__":
main()
Now, when you import the script containing this code using e.g. import module1
, it will not be run.
But, you can call module1.main()
wherever you need to run that code, and it will work as many times as you want.
I’ve written a question about this project I’m working on already (see Executing a python file from another for my project’s structure), but I’ve encountered a new issue. In the previous question, the tip I was given was to either use import statements or subprocesses. When I tried imports, I was able to navigate to each file one time only. Per the answer given to me, I next tried to use subprocesses so I could use each file multiple times. This is the current iteration of my code that I am using. Note that all of my programs are meant to be interactive in the python terminal.
import subprocess
f = open("readme_files/index.txt")
p = open("readme_files/projects.txt")
print(f.read())
func = 0
while True:
func = int(input("Requested Operation: "))
if func == 0:
print(p.read())
elif func == 1:
subprocess.run("projects/dice_app.py")
break
elif func == 2:
subprocess.run("projects/text_to_math.py")
break
else:
req_op = ''
print("Invalid operation. Please try again.")
I don’t really understand how these subprocesses work and the tip I was given didn’t work, returning this set of errors. Note I am using MS VScode with the Python 3.10.6 SDK:
File "[my user directory]Python Projectsstart_here.py", line 14, in <module>
subprocess.run("projects/dice_app.py")
File "C:Program FilesPython310libsubprocess.py", line 501, in run
with Popen(*popenargs, **kwargs) as process:
File "C:Program FilesPython310libsubprocess.py", line 969, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:Program FilesPython310libsubprocess.py", line 1438, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
OSError: [WinError 193] %1 is not a valid Win32 application
I don’t really understand what any of this means, so any help is much appreciated.
Likely, the reason you can only use the imports once is that the imported Python scripts do not contain methods but runnable code. Therefore, adjust your imported Python scripts into defined methods. Then, you can import whole script or specific underlying methods to be called as many times as needed in top level script.
Additionally, consider reading all text files in context managers to ensure they close properly. Be careful you are not reading large amounts of text with read()
, otherwise loop across lines. Even encapusulate text reads in functions and call as needed. Finally, consider a dictionary and avoid the the multiple if
/elif
conditions.
from projects.dice_app import my_dice_app_func
from projects.text_to_math.py import my_text_to_math_func
def print_index():
with open("readme_files/index.txt") as f:
print(f.read())
def print_projects():
with open("readme_files/projects.txt") as p:
print(p.read())
return 0
def invalid_input():
print("Invalid operation. Please try again.")
return ''
print_index()
func_dict = {
0 = print_projects,
1 = my_dice_app_func,
2 = my_text_to_math_func
}
func = 0
while True:
func = int(input("Requested Operation: "))
req_func = func_dict.get(func, invalid_input)
req_op = req_func()
if not req_op in [0, '']:
break
Subprocesses are not a proper solution for your problem. You said your imports didn’t work (only executed once) – that’s because you used them wrong. Imports are not supposed to be used as a standard piece of code. When you import something, all of the top-level code is executed in order to define the variables. On any further import of the same script, those variables are simply reused, that’s why it is not executed again.
First, make sure your imports have no side effects. All of the top-level code should be moved into a function, e.g. main()
. Then you can use very common clause if __name__=="__main__":
to make sure this function will not be executed on import.
So, let’s say your script contains the following:
i = 10
x = 12
print(i / x)
In order to make it work properly with imports, change it to something like that:
def main():
i = 10
x = 12
print(i / x)
if __name__ == "__main__":
main()
Now, when you import the script containing this code using e.g. import module1
, it will not be run.
But, you can call module1.main()
wherever you need to run that code, and it will work as many times as you want.