Timer that runs in the background in Python 3.7.0 - python-3.x

I am trying to make a timer in my text-based adventure games so that for every second that passes, 1 hp is taken away from the user, while they are in a certain scenario and can still use other functions. Here's my code:
#Imports and base variables
import time
import threading
import random
hp=100 #Health
p="snow" #Starting point
invtry=[] #Inventory of Character
#Function to drop health
def hlthdrp():
hp-1
t=threading.Timer(1.0,hlthdrp)
t.start()
while p=="snow" or p=="Snow":
if hp==0 and p=="snow" or p=="Snow":
print ("You died of frostbite")
t.cancel()
threading.wait(timeout=5.0)
As of right now, I'm not getting any errors, but instead, a completely blank shell, or terminal. If anyone could help, that'd be great!

You must call threading.Timer recursively else it only calling one time
And you can use lower() function to compare snow or some string
There is your fixed code i hope it will be usefull for you.
def hlthdrp():
global hp
print(hp)# just for testing
hp=hp-1
if hp!=0:
threading.Timer(1, hlthdrp).start()
hlthdrp()
while p.lower()=="snow":
if hp==0 :
print ("You died of frostbite")
elif hp!=0 :
pass

Related

Can UI interact while program loop through several task

I´m developing a program that handles many task in a sequence. I call this mode "AutoMode". But i need to let the user take control and start using the program manual, through menu options, and finally choose "AutoMode" again.
How can I interrupt the "AutoMode" without stopping the program executing. Guess input() will keep the program wait for ever for user to make an input and the rest of the code will stop executing?
Any suggestions?
Found a solution that solve this issue, but seems to need several keyboard interacts.
In example below this results in many keypress to get the while loop to enter the if statement and take the program back to main menu.
import keyboard
import time
my_counter = 1
while True:
my_counter += 1
if keyboard.is_pressed('h'):
print("Letter H was pushed")
time.sleep(2)
break
print("Something is going on... ", my_counter)
time.sleep(0.5)
print("Simulate user interupt and return to main menu...")

how to put a whole script into a loop?

I have 0 experience in coding but I put my ambition and code something in python for a game. Everything works perfect :D
But I have a problem. I don't know how to infinite repeat the code. I've look over the internet but i didn't understand much.
Im gonna let here a part of the code maybe someone can explain me how to put all code into 'repeat'.
import time
import pyautogui
pyautogui.click(942, 642)
time.sleep(1)
pyautogui.click(807, 581)
time.sleep(1)
Thanks.
Simply wrap it all (or, well, not the imports) in a while True: loop.
import time
import pyautogui
while True:
pyautogui.click(942, 642)
time.sleep(1)
pyautogui.click(807, 581)
time.sleep(1)

Can a tkinter button return a value from an entry on-click?

I'm doing an extended project as one of my qualifications in my current College and I chose to write a python Strategy/RPG game. As a result, I ended up with the highest level of Python knowledge (Surpassing my Computing Teacher who only ever uses the basics... and used Tkinter only once a few years ago. Every one else who has decided to make a program, are either coding in Lua, Java, C++, HTML/CSS/Java-Script or, those who are coding in python, they are only using the basics learned from our teacher.)
I say "Highest level of Python knowledge" but really it isn't that high... I only know a little beyond the basics.
As a result, a forum post is the best place I can turn to for help.
So in my game I defined this function:
#"Given_String" is the question that one would want to ask. (With the answer being an integer between 1 and "Choice_Range" (inclusive)
def Value_Error(Given_String,Error_Message,Choice_Range):
while True:
try:
Temp=int(input(Given_String))
if Temp<1 or Temp>Choice_Range:
print(Error_Message)
else:
break
except ValueError:
print(Error_Message)
return Temp
I then wanted to add tkinter to my code, because the game would have to be in a separate window, and not in the console. As a result, I had to change this code so that it displays the "Given_Message" and the "Error_Message" in a tkinter window, and uses the value that has been typed into an entry box when defining "Temp".
I wrote this code to make this work: (Or at least most of it)
#This code is stored in a different file for neatness and hence I had to import "sys" to avoid circular imports.
#This code is made to be flexible so that I can later re-use it when necessary.
#This code starts with the function all the way at the bottom. The rest are made to add flexibility and to structure the algorithm.
#This code hasn't been fully run (Because of the Error crashing the Python Shell) so it can contain other Run-time Errors that I'm not aware of yet.
import sys
def Generate_Window(Window_Name,X_Parameter=5,Y_Parameter=50):
Temp=sys.modules['tkinter'].Tk()
Temp.title(Window_Name)
Temp.geometry(str(X_Parameter)+"x"+str(Y_Parameter))
return Temp
def Generate_Button(Master,Text="Submit"):
Temp=sys.modules["tkinter"].Button(Master,text=Text)
return Temp
def Generate_Entry(Master):
Temp=sys.modules["tkinter"].Entry(Master)
return Temp
def Generate_Label(Master,Given_String):
Temp=sys.modules["tkinter"].Label(Master,text=Given_String)
return Temp
def Com_Get_Entry(Given_Window,Given_Entry):
Temp=Given_Entry.get()
Given_Window.destroy()
return Temp
def Com_Confirm(Given_Window):
Given_Window.destroy()
def Generate_Entry_Box(Given_String):
Entry_Window=Generate_Window("Entry",X_Parameter=300)
Entry_Label=Generate_Label(Entry_Window,Given_String)
Entry_Entry=Generate_Entry(Entry_Window)
Entry_Button=Generate_Button(Entry_Window)
Entry_Button.configure(command=lambda:Com_Get_Entry(Entry_Window,Entry_Entry))
Entry_Label.grid(row=0,columnspan=2)
Entry_Entry.grid(row=1,column=0)
Entry_Button.grid(row=1,column=1)
def Generate_Alert_Message(Given_String):
Alert_Window=Generate_Window("Alert",X_Parameter=300)
Alert_Label=Generate_Label(Alert_Window,Given_String)
Alert_Button=Generate_Button(Alert_Window,Text="OK")
Alert_Button.configure(command=lambda:Com_Confirm(Alert_Window))
Alert_Label.grid(row=0,columnspan=2)
Alert_Button.grid(row=1,column=1)
def Get_Interger_Input_In_Range(Given_String,Error_Message,Choice_Range):
while True:
try:
Returned_Value=int(Generate_Entry_Box(Given_String))
if Returned_Value<1 or Returned_Value>Choice_Range:
Generate_Alert_Message(Error_Message)
else:
break
except ValueError:
Generate_Alert_Message(Error_Message)
return Temp
I already included in my code all that I was struggling with and that I could find an answer to.
I.E: On-click, do a certain action with given parameters.
One thing I could not find, is how to return the entered value to the original (Get_Interger_Input_In_Range()) function after the button has been clicked.
What I mean is something like this:
def Function1(GivenParameter1,GivenParameter2):
Temp=Function2(GivenParameter1)
Temp+=GiverParameter2 #random action
return Temp
def Function2(GivenParameter):
Button=Button(Master,command=Function3).grid()
Entry=Entry(Master).grid()
def Function3():
Temp=Entry.get()
return Temp
In Function1 I want Temp to equal the entered value from Function2.
Is there any way to do this without using classes? (I'm not too familiar with classes yet)
Is there any way to do this at all?
I haven't seen anyone give the answer I was looking for...
Because even if they said to use classes... I still didn't know how to return it (Explanation just below)
#The following code was written quickly for purposes of explaining what I mean. It doesn't actually work... (It seems that the button command is being called automatically...)
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Button=Button(self.Master,text="Submit",command=self.Return())
def Return(self):
self.TempVar=self.Entry.get()
return self.TempVar
The way I see it, the Return() function would return the value to the button and not the function/assignment that called the class ... Which is the same problem I'm having with my code.
If you read this all then I really appreciate it. I hope someone can answer my question and tell me (if it's impossible otherwise) how to use classes to solve my "Little" yet large problem.
I fixed your example code (I think). The main problem is that this:
command=self.Return()
does not do what you think it does. It just assigns return value from Return() to command. This is incorrect. It should be
command=self.Return
This assigns function Return to command. Subsequently, when ever button is pressed, self.Return() is executed.
The full example is here:
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Entry.pack()
self.Button=Button(self.Master,text="Submit",command=self.Return)
self.Button.pack()
self.Master.mainloop()
def Return(self):
self.TempVar=self.Entry.get()
print(self.TempVar)
Return_Value_In_Entry()
Now, whenever you press the Button, the value from the Entry widget is saved into self.TempVar and printed out, just to check if its working. Hope this helps.
Gif showing how the example program works:

Refresh PyGTK window every minute?

I have a PyGTK app that is supposed to be a desktop monitor of some data source. I have it almost complete but there is just this one problem of auto-refreshing.
In my program I want it to fetch data from database and refresh the window every minute. Here's what I have for the refresh function (it refresh once per second now for testing):
def refresh(self):
cnxn = pyodbc.connect(r'Driver={SQL Server};Server=IL1WP0550DB;Database=Customer_Analytics;Trusted_Connection=yes;')
cursor = cnxn.cursor()
cursor.execute("SELECT * FROM TestGroup_test_group_result")
data = []
while 1:
row = cursor.fetchone()
if not row:
break
#data.append([row.TestGroupName, row.PWF, row.Expires, row.TestGroupID])
data.append([str(datetime.now()), row.PWF, row.Expires, row.TestGroupID])
cnxn.close()
self.fill_text(data)
threading.Timer(1, self.refresh).start()
Using this function I can update my window, but it only works when I drag my window around. When I put a series of print statements around, it looks like it is only executing the script when the window is moving.
Anyone know how to fix it?
Additional info: I realize that it only processes the refresh when there is a signal.
With GTK you need to make sure your widgets are only updated from the main thread. You can do this by using a timeout function with gtk.timeout_add() or gtk.timeout_add_seconds(). If you use python's threading functions the widgets are not updated from the main thread and so it does not work. For timeouts of greater than one second you should use gtk.timeout_add_seconds() as it avoids unnecessary wake ups where the timing isn't that critical.
Use gtk.timeout_add(1000, self.refresh) instead of threading.Timer(1, self.refresh).start() did the trick :)
Don't know why though
python3:
from gi.repository import GObject
def refresh_data(self):
[do stuff here]
if self.running:
GObject.timeout_add(1000, self.refresh_data)
Set self.running to False to stop.

Python 3.2 _thread module produces no output using Ubuntu 12.04, but works fine with windows 7

I'm hoping that someone has a quick and easy solution to this issue that I'm facing. I'm working through chapter 5 of the 4th edition of the Programming Python book by Mark Lutz and I'm having some troubles beginning on page 189. Basically, there is a very simple example:
import _thread
def action(i):
print(i ** 32)
_thread.start_new_thread(action, (2, ))
For some reason, this script will not produce any output on my pc running Ubuntu 12.04, but will on my windows 7 machine. The output when run from the terminal is:
un#homepc:~/Desktop/pp$ python3.2 thread1.py
un#homepc:~/Desktop/pp$
Any help would be much appreciated.
Thanks.
I am not an expert of threads but this is most likely the problem:
When running this code, Python has nothing to do after the last line;so it exits forcefully ending the thread (whether it completed or not).
Depending on how the threads run, the thread may complete or it may not. (unreliable behaviour)
main thread pseudo-code instruction:
create the new thread
new thread:
action(2)
main thread next instruction:
program ended;exit
Fixed code:
import _thread
def action(i):
print(i ** 32)
action_lock.release() #Now Python will exit
#locks are a part of threaded programming; if you don't know what it is, you can google it.
action_lock = _thread.allocate_lock() #set a lock for the action function thread
action_lock.acquire() #Acquire the lock
_thread.start_new_thread(action, (2, ))
action_lock.acquire()
Thanks to Ramchandra for pointing me in the right direction. The problem was that the program was ending and killing the threads. If I run this:
import time, _thread
def print_t(name, delay):
while True:
try:
time.sleep(delay)
print(name)
except: pass
_thread.start_new_thread(print_t, ("First Thread", 1,))
_thread.start_new_thread(print_t, ("Second Thread", 2,))
while True:
try: pass
except KeyboardInterrupt:
print("Ending main program")
break
... then the program executes as planned. I don't have an answer as to why the code in the original post worked on windows 7, but not on ubuntu 12.04. Oh well. Hope this helps someone, sometime.

Resources