How to Fix: Main function is Unreachable - Python 3.5 - python

I'm trying to make a dead-simple bot according to this video: https://www.youtube.com/watch?v=5Jwd69MRYwg
The main function that is supposed to be called when a part of the screen changes color simply is not being run at all.
I've tried ending the program with
"main()"
and
"if __name__ == '__main__':
main()"
respectively. Neither have allowed the code to run
def restart_game():
time.sleep(1)
pyautogui.click(Coordinates.replayBtn)
def image_grab():
box = (290, 465, 305, 487)
image = image_grab_lib.grab(box)
grey = ImageOps.grayscale(image)
a = array(grey.getcolors())
print(a.sum())
return a.sum()
def main():
restart_game()
print("blip")
if image_grab() != 577:
print("Jump")
press_space()
time.sleep(1)
restart_game()
if __name__ == '__main__':
main()
I expect the main function to run and give print "blip" and "jump", currently running all the other code and entirely skipping the main function.
shows what the warning looks like in PyCharm - image

Your code is unreachable because you have an infinite while loop before main() definition. It's a good practice in applications that require while loop to put it inside if name == 'main' condition after all variables are declared.
Like this:
if __name__ == '__main__':
while True:
do_something()

Related

How to stop the execution of an imported python script without exiting the python altogether?

In the example below, when I run y_file.py, I need 5 printed and Hello not printed.
How to stop the execution of an imported python script x_file.py without exiting the python altogether? sys.exit() seems to exit python altogether.
x_file.py
import sys
x = 5
if __name__ != '__main__':
pass
# stop executing x.py, but do not exit python
# sys.exit() # this line exits python
print("Hello")
y_file.py
import x_file
print(x_file.x)
As jvx8ss suggested, you can fix this by putting the print inside a if __name__ == "__main__": conditional. Note the equality "==" instead of inequality "!=".
Final code:
import sys
x = 5
if __name__ == "__main__":
# stop executing x.py, but do not exit python
# sys.exit() # this line exits python
print("Hello")
You should place your code you don't want to run in the import inside an if __name__ == "__main__" however, there is an extremely bad way to do what you want that I can think of using Exception
# x_file.py
x = 5
if __name__ != '__main__':
raise Exception(x)
print("Hello")
# y_file.py
try:
import x_file
except Exception as e:
print(e.args[0])

Python multiprocessing creates sub-process using wrong function

I'm trying to write code that create sub-process using another module(demo_2.py),
and exit program if i get wanted value on sub-processes.
But result looks like this.
It seems that demo_1 makes two sub-process that run demo_1 and load demo_2.
I want to make sub-process only runs demo_2.
What did i missed?
demo_1.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from multiprocessing import Process,Queue
import sys
import demo_2 as A
def multi_process():
print ("Function multi_process called!")
process_status_A = Queue()
process_status_B = Queue()
A_Process = Process(target = A.process_A, args = (process_status_A,))
B_Process = Process(target = A.process_A, args = (process_status_B,))
A_Process.start()
B_Process.start()
while True:
process_status_output_A = process_status_A.get()
process_status_output_B = process_status_B.get()
if process_status_output_A == 'exit' and process_status_output_B == 'exit':
print ("Success!")
break
process_status_A.close()
process_status_B.close()
A_Process.join()
B_Process.join()
sys.exit()
print ("demo_1 started")
if __name__ == "__main__":
multi_process()
demo_2.py
class process_A(object):
def __init__(self, process_status):
print ("demo_2 called!")
process_status.put('exit')
def call_exit(self):
pass
if process_status_A == 'exit' and process_status_B == 'exit':
should be
if process_status_A_output == 'exit' and process_status_B_output == 'exit':
Conclusion: The naming of variables is important.
Avoid long variable names which are almost the same (such as process_status_A and process_status_A_output).
Placing the distinguishing part of the variable name first helps clarify the meaning of the variable.
So instead of
process_status_A_output
process_status_B_output
perhaps use
output_A
output_B
Because Windows lacks os.fork,
on Windows every time a new subprocess is spawned, a new Python interpreter is started and the calling module is imported.
Therefore, code that you do not wish to be run in the spawned subprocess must be "protected" inside the if-statement (see in particular the section entitled "Safe importing of main module"):
Thus use
if __name__ == "__main__":
print ("demo_1 started")
multi_process()
to avoid printing the extra "demo_1 started" messages.

Breaking if __name__ when a condition is not met

I am using
if __name__ == "__main__":
to run my defined functions.
However as an error catching measure I am trying to implement a way to ensure that file paths have been entered correctly into the .bat file my script is ran from, the file names are passed in as arguments.
What I am doing is defining a function to define whether certain arguments are "valid", things such as
.endswith("\\")
or
.endswith(".txt")
however because they are within an if block (if __name__ == "main"`) I am struggling to work out how to stop the script there.
I basically want to apply my validation function to all the arguments and if any return False then to stop the __main__ function and show an error message in such a way:
print len(invalid_args), " arguments are invalid, please check input"
However using a break here is showing as "Break is outside of loop" in pycharm.
How can I stop the rest of my script running if validation returns False and it is all contained in the if __name__ == "__main__" block?
Here is a representation of my code, but without the unnecessary detail:
def clean():
do_something()
def merge():
do_something_else()
def valid()
if valid:
return True
if not valid:
return False
if __name__ == "__main__":
if not valid():
"Stop script here" # This is the part I don't know how to do
if valid():
try:
clear()
except Exception a e:
print e + "Something Went Wrong"
try:
merge()
except Exception as e:
print e + "Something Went Wrong"
break is used to break out of a loop (as PyCharm has told you).
Instead you could have the following code which will run your tests and if true not allow the rest of the content to proceed.
# Your code ...
def some_function():
# Something function that runs your tests
# If your tests fail then return True, otherwise return False
if __name__ == '__main__':
if some_function():
print("Sorry but your .bat file must be broken!")
else:
# Run the rest of your code happily.
You could even raise an Exception as opposed to just printing a message.
if is not a "loop". You can only break from for or while (which are loops). To stop the program outside of a loop, you have a few options:
raise an error;
sys.exit the whole program; or
guard the rest of the code with another if.
For example:
if __name__ == "__main__":
valid_args, invalid_args = process(args)
if invalid_args:
# raise error or exit
# rest of code
or:
if __name__ == "__main__":
valid_args, invalid_args = process(args)
if invalid_args:
# print warning
else:
# rest of code
Within a function, you can also return:
def main():
valid_args, invalid_args = process(args)
if invalid_args:
return
# rest of code
if __name__ == "__main__":
main()
Move all of your logic under if __name__ == "__main__" into a separate function, and replace your if __name__ == "__main__" block with just
if __name__ == "__main__":
doMySetupStuff()
Inside your doMySetupStuff function, you can check the arguments and return if you find any of them are not valid.

main program while loop

I have a little Python program that uses keyboard input to run certain commands.
I setup everything in one main program loop but now I'm wondering, do I even need a main loop?
Here is what I mean:
mainProgramLoop = 1
while mainProgramLoop == 1:
print ("\nType in the command. ")
keyBoardInput= input("command:")
if keyBoardInput == "a":
#do this
elif keyBoardInput == "b":
#do this
Do I actually need that while loop?
Thanks!
No, you do not need a main loop if you use the cmd.Cmd class included with Python:
#! /usr/bin/env python3
import cmd
class App(cmd.Cmd):
prompt = 'Type in a command: '
def do_a(self, arg):
print('I am doing whatever action "a" is.')
def do_b(self, arg):
print('I am doing whatever action "b" is.')
if __name__ == '__main__':
App().cmdloop()
The documentation for the cmd module includes an example near the bottom to help get you started.

Multiprocessing beside a main loop

I'm struggling with a issue for some time now.
I'm building a little script which uses a main loop. This is a process that needs some attention from the users. The user responds on the steps and than some magic happens with use of some functions
Beside this I want to spawn another process which monitors the computer system for some specific events like pressing specif keys. If these events occur then it will launch the same functions as when the user gives in the right values.
So I need to make two processes:
-The main loop (which allows user interaction)
-The background "event scanner", which searches for specific events and then reacts on it.
I try this by launching a main loop and a daemon multiprocessing process. The problem is that when I launch the background process it starts, but after that I does not launch the main loop.
I simplified everything a little to make it more clear:
import multiprocessing, sys, time
def main_loop():
while 1:
input = input('What kind of food do you like?')
print(input)
def test():
while 1:
time.sleep(1)
print('this should run in the background')
if __name__ == '__main__':
try:
print('hello!')
mProcess = multiprocessing.Process(target=test())
mProcess.daemon = True
mProcess.start()
#after starting main loop does not start while it prints out the test loop fine.
main_loop()
except:
sys.exit(0)
You should do
mProcess = multiprocessing.Process(target=test)
instead of
mProcess = multiprocessing.Process(target=test())
Your code actually calls test in the parent process, and that call never returns.
You can use the locking synchronization to have a better control over your program's flow. Curiously, the input function raise an EOF error, but I'm sure you can find a workaround.
import multiprocessing, sys, time
def main_loop(l):
time.sleep(4)
l.acquire()
# raise an EOFError, I don't know why .
#_input = input('What kind of food do you like?')
print(" raw input at 4 sec ")
l.release()
return
def test(l):
i=0
while i<8:
time.sleep(1)
l.acquire()
print('this should run in the background : ', i+1, 'sec')
l.release()
i+=1
return
if __name__ == '__main__':
lock = multiprocessing.Lock()
#try:
print('hello!')
mProcess = multiprocessing.Process(target=test, args = (lock, ) ).start()
inputProcess = multiprocessing.Process(target=main_loop, args = (lock,)).start()
#except:
#sys.exit(0)

Categories

Resources