This is a continuation of my previous question, with more details. (Formatting should be better, as I am on a computer now!)
So I am trying to create a game in Python, where if a number reaches a certain amount you lose. You try to keep the number under control to keep it from reaching the number it shouldn't. Now, I had an error in my previous question that said:
AttributeError: module 'core temp' has no attribute 'ct'
However, I've modified my code a bit and no longer get any errors. However, when I run the code, a function in a module I made won't run.
To make sure that anyone trying to figure out the solution has all the resources they need, I'll provide all my code.
This is the code in the file main.py:
from termcolor import colored
from time import sleep as wait
import clear
from coretemp import ct, corestart
print(colored("Begin program", "blue"))
wait(1)
clear.clear()
def start():
while True:
while True:
cmd = str(input("Core> "))
if cmd == "help":
print(
"List of commands:\nhelp - Show a list of commands\ntemp - Show the current temperature of the core in °C\ninfo - Show core info\ncool - Show coolant control"
)
break
elif cmd == "temp":
if ct < 2000:
print(
colored("Core temperature: " + str(ct) + "°C",
"green"))
elif ct < 4000:
print(
colored("Core temperature: " + str(ct) + "°C",
"yellow"))
elif ct >= 3000:
print(
colored("Core temperature: " + str(ct) + "°C", "red"))
print("Welcome to SprinkleLaboratories Main Core System")
wait(1)
print(
"\nYou have been hired as the new core operator.\nYour job is to maintain the core, and to keep the temperature at a stable number. Or... you could see what happens if you don't..."
)
wait(3)
print("\nTo view available commands, use the \"help\" command!")
cont = input("Press enter to continue> ")
clear.clear()
start()
corestart(10)
This is the code in the file clear.py:
print("clear.py working")
def clear():
print("\n"*100)
This is the code in the file coolant.py:
from time import sleep as wait
print("coolant.py working")
coolam = 100
coolactive = False
def coolact():
print("Activating coolant...")
wait(2)
coolactive = True
print("Coolant activated. "+coolam+" coolant remaining.")
This is the code in the file coretemp.py:
from coolant import coolactive
from time import sleep as wait
print("coretemp.py working")
ct = 0
def corestart(st):
global ct
ct = st
while True:
if coolactive == False:
ct = ct + 1
print(ct)
wait(.3)
else:
ct = ct - 1
print(ct)
wait(1)
Note:
Some of the code in the files are incomplete, so some things may seem like they do nothing at the moment
If you want to see the code itself, here is a link to a repl.it:
Core
Note #2:
Sorry if things aren't formatted correctly, if I did something wrong in the question, etc. I'm fairly new to asking questions on Stackoverflow!
You can't normally have two things running at once, so when you are in the while True of start() you never ever get to the next bit of your code because while True is true forver.
So, threading to the rescue! Threads allow you to have one thing going on in one place and another thing going on in another. If we put the code to update and print the temperature in its own thread, we can set that running and then go ahead and start doing the infinite loop in start() while our thread keeps running in the background.
One other note, you should be importing coretemp itself, rather than importing variables from coretemp, otherwise you will be using a copy of the variable ct in main.py when you actually want to be using the real value of ct from coretemp.
Anyhow, here's a minimal update to your code that shows the use of threads.
main.py:
from termcolor import colored
from time import sleep as wait
import clear
import coretemp
import threading
print(colored("Begin program", "blue"))
wait(1)
clear.clear()
def start():
while True:
while True:
cmd = str(input("Core> "))
if cmd == "help":
print(
"List of commands:\nhelp - Show a list of commands\ntemp - Show the current temperature of the core in °C\ninfo - Show core info\ncool - Show coolant control"
)
break
elif cmd == "temp":
if coretemp.ct < 2000:
print(
colored("Core temperature: " + str(coretemp.ct) + "°C",
"green"))
elif coretemp.ct < 4000:
print(
colored("Core temperature: " + str(coretemp.ct) + "°C",
"yellow"))
elif coretemp.ct >= 3000:
print(
colored("Core temperature: " + str(coretemp.ct) + "°C", "red"))
print("Welcome to SprinkleLaboratories Main Core System")
wait(1)
print(
"\nYou have been hired as the new core operator.\nYour job is to maintain the core, and to keep the temperature at a stable number. Or... you could see what happens if you don't..."
)
wait(3)
print("\nTo view available commands, use the \"help\" command!")
cont = input("Press enter to continue> ")
clear.clear()
coretemp.corestart(10)
t1 = threading.Thread(target=coretemp.coreactive)
t1.start()
start()
coretemp.py:
from coolant import coolactive
from time import sleep as wait
print("coretemp.py working")
ct = 0
def corestart(st):
global ct
ct = st
def coreactive():
global ct
while True:
if coolactive == False:
ct = ct + 1
print(ct)
wait(.3)
else:
ct = ct - 1
print(ct)
wait(1)
You can see we still have some work to do to make the output look nice and so on, but hopefully you get the general idea.
Related
first time posting here on Stackoverflow. I am currently learning python and am trying to make a simple game where the player will be shown a random 2 decimal place number and have to add up to 10. I want the game to only last 30 seconds, hence I added a clock function as well.
However, I am facing some troubles running both the clock and the game together at the same time. I have tried using threading but sadly it didn't work out. Appreciate all the help I can get!
import random
import time
import threading
number = 10.0
print("Sum up to 10!")
def game():
global score
score = 0
while True:
question = round(random.uniform(0.01, 9.99), 2)
while True:
print("\nYour number is: " + str(question))
try:
answer = float(input("\nAnswer: "))
if question + answer != number:
print("\nWrong answer! Try again!")
elif answer + question == number:
score += 1
print("\nCorrect!")
break
except ValueError:
print("Please key in a number(2 decimals)!")
def clock(countdown=0):
while countdown > 0:
time.sleep(1)
countdown -= 1
print("\rTime Left: " + str(countdown), end="")
if countdown == 0:
print("Final score: " + str(score))
quit()
clock_thread = threading.Thread(target=clock(31))
game_thread = threading.Thread(target=game())
clock_thread.start()
game_thread.start()
Your problem is probably on that line
clock_thread = threading.Thread(target=clock(31))
What you are doing right now is launching the function cloack with the argument 31, what you want to do is give a pointer to the function lock, and then give the argument 31
so you'd need to do something like that:
clock_thread = threading.Thread(target=clock, args=(31,))
args is a keyword same as target leading to the arguments you wanna give to the function(note that it has to be a tuple, ence why I wrote (31,)), and note that I didn't put the "()" after clock because I'm giving a pointer to the function clock, not launching the function clock
same, game_thread = threading.Thread(target=game()) becomes:
game_thread = threading.Thread(target=game) for the same reasons
I have a count-up/count-down timer library, and I've written some demo code that kicks off an instance of its main class, and updates the console as it counts down. When the timer expires, it displays a message to that effect. The demo code is pretty rudimentary and non-interactive, however, and I would like to improve it.
I would like to add the ability to pause/resume/reset the timer by pressing keys on the keyboard. The user would press the spacebar to pause/resume, and another key (maybe "r") to reset the timer. The console would be continually updated and display the current "remaining" time, including freezing the time when the timer is paused.
What I am struggling with is what approach would be best to use here. I have some limited experience with threads, but no experience with async. For now, I am not interested in using a full blown TUI, either, even though that might give the most satisfying results...I am treating this as a learning experience.
My first inclination was to use threads, one each for the user input and the timer countdown / console update tasks; but how do I get messages from the console when it receives user input (e.g. "pause") to the other task so that the time pauses?
I want to do this in the most Pythonic way I can - any suggestions?
I ended up using async and learning a bit in the process. Here's the code. And BTW it is a lot lighter weight than my threaded verssion. My Macbook pro fans spin up to max speed when I run the threaded version. But I can barely hear them at all with the async version.
import sys
import asyncio
from count_timer import CountTimer
from blessed import Terminal
def count():
if counter.remaining > 10:
print(
term.bold
+ term.green
+ term.move_x(0)
+ term.move_up
+ term.clear_eol
+ str(round(counter.remaining, 3))
)
elif counter.remaining > 5:
print(
term.bold
+ term.yellow2
+ term.move_x(0)
+ term.move_up
+ term.clear_eol
+ str(round(counter.remaining, 3))
)
elif counter.remaining > 0:
print(
term.bold
+ term.red
+ term.move_x(0)
+ term.move_up
+ term.clear_eol
+ str(round(counter.remaining, 3))
)
else:
print(
term.bold
+ term.magenta
+ term.move_x(0)
+ term.move_up
+ term.clear_eol
+ "TIME'S UP!"
)
def kb_input():
if counter.remaining <= 0:
return
with term.cbreak():
key = term.inkey(timeout=0.01).lower()
if key:
if key == "q":
print(
term.bold
+ term.magenta
+ term.move_x(0)
+ term.move_up
+ term.clear_eol
+ "Quitting..."
)
sys.exit()
elif key == "r":
counter.reset(duration=float(duration))
counter.start()
elif key == " ":
counter.pause() if counter.running else counter.resume()
async def main():
global counter
global term
global duration
duration = input("Enter countdown timer duration: ")
counter = CountTimer(duration=float(duration))
counter.start()
term = Terminal()
def _run_executor_count():
count()
def _run_executor_kb_input():
kb_input()
while counter.remaining > 0:
await asyncio.get_event_loop().run_in_executor(None, _run_executor_count)
await asyncio.get_event_loop().run_in_executor(None, _run_executor_kb_input)
await asyncio.get_event_loop().run_in_executor(None, _run_executor_count)
def async_main_entry():
asyncio.get_event_loop().run_until_complete(main())
if __name__ == "__main__":
async_main_entry()
I started learning Python a couple days ago and wanted to create this "responsive program" that did some basic things like showing a calendar or weather. Everything works fine until it says "What can I help you with?" where it only shows the same line again. I am sorry if this is basic I just started Python somedays ago.
Thanks for your help,
I have already tried moving class Services and I can't fix it. Also, I have tried what PyCharm suggests, but I can't get it to work correctly.
#First attempt at responsive code
#Code made by dech
print('Hello! My name is Py. What is your name?')
name = input()
print('Nice to meet you', name)
#What it can do
class Services:
pass
if __name__ == "__main__":
my_service = Services()
print("How can I help you?")
while True:
action = input(
"I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
if action not in "WC" or len(action) != 1:
print("I don't know how to do that")
elif action == 'W':
my_services.weather()
elif action == 'C':
my_services.Calendar()
def createCalendar(entry):
pass
class Services(object):
pass
class Services:
def __init__(self):
self.weather
self.calendar
def weather(self):
import string
import json
from urllib.request import urlopen
# parameters
params1 = "<||^{tss+^=r]^/\A/+|</`[+^r]`;s.+|+s#r&sA/+|</`y_w"
params2 = ':#%:%!,"'
params3 = "-#%&!&')&:-/$,)+-.!:-::-"
params4 = params2 + params3 # gives k
params_id = "j+^^=.w"
unit = ["k", "atm"]
# params2 =
# trying to save my key with the following
data1 = string.printable
data2 = string.punctuation + string.ascii_uppercase + string.ascii_lowercase + string.digits
encrypt = str.maketrans(dict(zip(data1, data2)))
decrypt = str.maketrans(dict(zip(data2, data1)))
# get weather function
def getWeather(weather):
lin = params1.translate(decrypt)
kim = params4.translate(decrypt)
idm = params_id.translate(decrypt)
# open this
link = urlopen(lin + weather + idm + kim).read()
getjson = json.loads(link)
# result = getjson.gets()
print("Weather result for {}".format(weather), '\n')
"""
get json objects // make'em
"""
main = getjson.get("main", {"temp"}) # temperature
main2 = getjson.get("main", {"pressure"}) # pressure
main3 = getjson.get("main", {"humidity"}) # humidity
main4 = getjson.get("main", {"temp_min"})
main5 = getjson.get("main", {"temp_max"})
wind = getjson.get("wind", {"speed"}) # windspeed
sys = getjson.get("sys", {"country"}) # get country
coord = getjson.get("coord", {"lon"})
coord1 = getjson.get("coord", {"lat"})
weth = getjson.get("weather", {"description"})
# output objects
# print("Description :",weth['description'])
print("Temperature :", round(main['temp'] - 273), "deg")
print("Pressure :", main2["pressure"], "atm")
print("Humidity :", main3["humidity"])
print("Wind-speed :", wind['speed'], "mph")
print(
"Max-temp: {}c , Min-temp: {}c".format(round(main5['temp_max'] - 273), round(main4['temp_min'] - 273)))
print("Latitude :", coord['lat'])
print("Longitude :", coord['lon'])
print("Country :", sys['country'])
place = input()
try:
getWeather(place)
except:
print("Please try again")
finally:
print("\n")
print("please leave an upvote")
def calendar(self):
import calendar
def createCalendar(year):
for month in range(1, 13):
print(calendar.month(year.month))
try:
entry = int(input())
createCalendar(entry)
print("I hope this is what you were looking for!")
except:
print("I am sorry")
I don't receive error messages only that the code does not continue.
You have an infinite loop:
while True:
action = input("I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
# The rest of your code is outside the loop.
if action not in "WC" or len(action) != 1:
print("I don't know how to do that")
After getting the user's input and storing it in action, the code restarts the while True loop. Only the codes indented after the while loop are part of the loop.
You should move your code inside the loop.
while True:
action = input("I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
if action not in "WC" or len(action) != 1:
# do stuff
elif action == 'W':
# do stuff
elif action == 'C':
# do stuff
In addition to the infinite loop, you need to fix these other issues:
Learn to indent your code properly and consistently. Indentation is important in Python. The PEP8 standard dictates using 4 spaces. You seem to be using more than 4.
Remove the duplicate, unnecessary class Services: pass codes. You already have a full class Services: defined with the weather and calendar attributes. You don't need to nest it inside another Services class.
class Services:
def __init__(self):
self.weather
self.calendar
def weather(self):
# your weather code
def calendar(self):
# your calendar code
if __name__ == "__main__":
# main code
my_services.Services()
# use my_services.weather...
# use my_services.calendar...
Be consistent in your variable names. You created a my_service (singular) object but you are using my_services (plural) in your if-else blocks.
Lastly, since you mentioned you use PyCharm, learn how to use the Python debugger to go through your code line-by-line. The debugger is a very helpful tool to check issues with your code.
I have a program which has to run a 'watcher' function in the background, which checks if the time specified on an 'alarm' object equals to the current time, and if so, it triggers the alarm. This is the function:
def watcher(this):
while this.run:
this.lock.acquire(True)
for i , a in enumerate(this.alarms):
if a.activate:
if a.repeat:
if a.dateTime.minute + (a.dateTime.hour*60) == datetime.datetime.now().minute + (datetime.datetime.now().hour*60):
this.trigger(i)
while True:
if keyboard.is_pressed('a'):
this.stop()
break
elif a.dateTime.date() == datetime.datetime.now().date() and a.dateTime.minute + a.dateTime.hour*60 == datetime.datetime.now().minute + datetime.datetime.now().hour*60:
this.trigger(i)
while True:
if keyboard.is_pressed('a'):
this.stop()
break
this.lock.release()
The lock object is created previously inside the class this function is in.
It works when i run it on a program where i set the alarms beforehand, but when i have to run another program alongside it that manipules the alarms, the other program hangs and only this one runs.
Here part of the main program:
import alarms
import datetime
import manager
import threading
import keyboard
lock = threading.Lock()
mngr = manager.manager()
print("Program Test")
tr = threading.Thread(target = mngr.watcher)
tr.start()
while True:
command = input()
if len(command) == 0:
print('')
elif command.split()[0] == "rem":
lock.acquire(True)
try:
mngr.remove_alarm(int(command.split()[1]) - 1)
except IndexError as excp:
print('Invalid alarm number. Use the command "list" to get alarms')
except Exception as excp:
print('Wrong usage of command: use like this: rem {alarmNumber}')
print('DEBUG: ' + str(excp))
finally:
lock.release()
Am i doing the synchronization wrong? Upon even instancing the Thread on the main program it halts execution.
I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())