Openai gym window wont close on env close - python-3.x

I am trying to implement simple cart pole code but pygame window doesnt close on env.close and freezes. When i try to manually close, it is restarting kernel. This is my code :
env = gym.make("CartPole-v1", render_mode = "human")
episodes = 5
for episode in range(1, episodes+1):
state = env.reset()
done = False
score = 0
while not done:
env.render()
action = env.action_space.sample()
n_state, reward, done,truncated, info = env.step(action)
score += reward
print("Episode:{} Score: {}".format(episode, score))
env.close()
I tried to declera env in different cell but nothing changed. I tried to uninstall and reinstall the packages but it same again. Anyone can help ?

I think that the problem is with env.render() function. It is not properly closing the window after the simulation is completed. Maybe you can try to add pygame.quit() after the while loop. Something like this:
env = gym.make("CartPole-v1", render_mode = "human")
episodes = 5
for episode in range(1, episodes+1):
state = env.reset()
done = False
score = 0
while not done:
env.render()
action = env.action_space.sample()
n_state, reward, done,truncated, info = env.step(action)
score += reward
print("Episode:{} Score: {}".format(episode, score))
pygame.quit()
env.close()
I hope it will help you.

Related

Box space always returning float values in OpenAI gym

I'm trying to get started with reinforcement learning using OpenAI Gym. I tried to tackle the Hotter-Colder exercise (https://gym.openai.com/envs/HotterColder-v0/).
For the action space, i am trying to pass a Box space to ensure it is a continuous space. Even though i am specifying the type as int32, when i train the model via model.learn it always gets the values as float32 between 0 and 2.5.
As you can see in the code below, the action_space is specified with a Box as int32 but during the training and prediction phase, the action value is always array[float32]. Furthermore, rather than get values between 1.0 and 100.0, the values seem to be stuck only between 0.0 and 2.5. Anyone know how to solve this?
Thank you very much.
Here is my code:
class HotterColder(Env):
def __init__(self):
self.range = 100
self.guess_max = 100
self.number = 0
self.guess_count = 0
self.action_space = Box(low=1,high=100,shape=(1,),dtype=np.int32)
self.observation_space = Discrete(4)
self.state = 0
np.random.seed(0)
def reset(self):
self.number = np.random.randint(low=1, high=self.range)
self.guess_count = 0
self.observation = 0
return self.state
def render(self):
pass
def step(self, action):
guess =int( action[0])
if guess < self.number:
self.state = 1
elif guess > self.number:
self.state = 3
else:
self.state = 2
self.guess_count += 1
done = self.guess_count >= self.guess_max
reward = ((min(guess, self.number) + self.range) / (max(guess, self.number) + self.range))**2
info = {"guess": guess, "actual": self.number, "guesses": self.guess_count, "reward": reward, "state": self.state}
if done:
if guess == self.number:
print("Correct guess." + str(info))
return self.state, reward, done, info

tkinter os.path.isfile, os.path.exists doesn't work and freeze the app

I just made a little program to make some plots with tkinter in python.
And I'm trying to make the app to create png file not overlapping the previous one.
So like, if it exists, rename it as ~ (1).png kinda thing.
But when I run os.path.isfile or os.path.exists, the app just freezes. Like, endless hourglasses turning and saying not responding, you know.
So, this is the function I binded with the button.
def get_information_S():
global nation_list, checked_list, output, year_menu, auto_flag, df
year = year_menu.get()
checked_list.sort()
nations = []
if auto_flag == 0:
for n in range(len(nation_list)):
nations.append(nation_list[n][0].get())
else:
pass
if len(year) == 0:
output_log("연도를 선택해주세요.\n")
elif len(checked_list) == 0:
output_log("hs코드를 선택해주세요.\n")
else:
output_log("\n\n분석 연도 : "+str(year)+"\n분석 품목 : "+str(checked_list)+"\n분석 국가 : "+str(nations)+"\n분석을 실시했습니다.\n")
for x in range(len(checked_list)):
os.makedirs("result", exist_ok=True)
os.makedirs("result\\single", exist_ok=True)
os.makedirs("result\\single\\hs_"+str(checked_list[x]),exist_ok = True)
df_test = df[df.hs6==int(checked_list[x])]
df_test = df_test[df_test.year==int(year)]
file_loc = "result\\single\\hs_"+str(checked_list[x])+"\\hs_"+str(checked_list[x])+"_"+str(year)+'.png'
f = -1
while True:
f+= 1
if os.path.isfile(file_loc) == True:
if f == 0:
file_loc = file_loc.replace('_.png','_('+str(f)+').png')
else:
file_loc = file_loc.replace('('+str(f-1)+')','('+str(f)+')')
continue
else:
break
plain_graph(df_test, file_loc, checked_list[x], nations)
Well, it's my first time dealing with GUI.
Is there a way I can use os.path.isfile or os.path.exists? Or any walkaround?
Thank you!
The initial value of file_loc is something like "result\\single\\hs_xxxx_2021.png" (assume year is 2021), then in the first iteration of the while loop, if f == 0 will be evaluated as True and so
file_loc = file_loc.replace('_.png','_('+str(f)+').png')
will be executed, but nothing will be replaced as _.png is not found in file_loc and so file_loc is kept as initial value and continue line will proceed to next iteration. As the file_loc does not change and f is increased, the else part
file_loc = file_loc.replace('('+str(f-1)+')','('+str(f)+')')
will be executed but again nothing is replaced as the search pattern is not found in file_loc.
Then same result happens for every iteration followed and make the while loop an infinite loop.
So the mentioned line should be changed to:
file_loc = file_loc.replace('.png','('+str(f)+').png')

pygame keylogger improvement ideas?

I'm currently writing a pygame keylogger based on the pygame event handler.
My old version was based on testing all available keys needed for my application but now, because of a huge loss of processing capacity in the old one, I have based it on retrieving the unprocessed information of the pressed key, searching for its place in the list, and making pygame put out its coherent string.
I have completed the first functional version and am open for some improvement ideas.
special = '''+#-.,´ß0987654321^<'''
konverted = '''*\'_:;`?=)(/&%$§"!°>'''
print(special, konverted)
def key_get():
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
key = pygame.key.get_pressed()
for i in range(0, 253, 1): #empirisch gemessen für 'ü' (letztes bei umlauten)
if key[i]:
name = pygame.key.name(i)
mod = pygame.key.get_mods()
if mod & pygame.KMOD_SHIFT:
if all([str(x) != str(name) for x in special]):
name = name.upper()
elif any([str(y) == str(name) for y in special]):
for y in range(0, len(special), 1):
if str(special[y])== str(name):
name = konverted[y]
elif event.type == pygame.MOUSEBUTTONDOWN:name = "mousebuttondown"
elif event.type == pygame.QUIT:name = False
elif event.type == pygame.VIDEORESIZE:
screen = pygame.display.set_mode(event.dict['size'], pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.RESIZABLE)
pygame.display.flip()
I'm not really sure what you mean for us to do, but is this what you want?
for event in pygame.event.get()
if event.type == pygame.KEYDOWN:
key_name = event.unicode

While true loops giving me recursion errors

I'm creating a game with pygame for my CompSci course. The game is working well, but now I'm trying to make a restart function and I'm getting alot of errors.
The basic outline of what I'm trying to do is:
first = True
def check(count):
if count == 1000:
return True
else:
return False
def start():
# MAIN MENU
print ("start")
count = 0
while True:
count += 1
if check(count) == True:
Game()
def Game():
count = 0
print("Game")
while True:
# GAMELOOP
count += 1
if check(count) == True:
restart()
def restart():
count = 0
print ("Restart")
while True:
# RESTART
count += 1
if check(count) == True:
start()
if first == True:
first = False
start()
However, whenever I run this, python ultimately crashes with:
RecursionError: maximum recursion depth exceeded while calling a Python object
I'm not sure about how to get around this. I was hoping that someone could suggest another method to do the same thing or something that I've done wrong.
The actual restart and menu functions:
def rest(): #Main Menu
while True:
pygame.display.update()
menu.draw()
if pygame.mouse.get_pressed()[0]:
x, y = pygame.mouse.get_pos()
if x >= 255 and x <= 355 and y >= 400 and y <= 450:
game()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def game(): #Gameloop
while True:
if bottom.time == 0 or bottom.time < 0 :
game_screen.fill((0, 0, 0))
restart()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def restart():
while True:
pygame.display.update()
menu.restart()
if pygame.mouse.get_pressed()[0]:
x, y = pygame.mouse.get_pos()
if x >= 255 and x <= 355 and y >= 400 and y <= 450:
game_screen.fill((0, 0, 0))
rest()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
Do you have a sequence of functions calling each other creating a indirect recursion.
start() counts to 1000 and then calls Game(), which counts to 1000 again and then calls restart(), whichs also counts to 1000 an then calls start(), closing the recursion loop. Once you do not have a stop condition, your recursion goes until reach the depth limit of python's recursion stack, then you get the exception.
As solution, you need to create a stop condition inside of one those functions.
Edit
I don't know pygame exactly but, as far as I get from the additional code, to the for in rest() function (which checks the events) be executed, it needs that the game() function returns, which are never happening. You can test this hyphotesis printing something just in the line before the for line. Same applies to the restart function.

Writing to an external file before a blackout

I have a python scoreboard program running on a raspberry pi, and I need it to recover the information on it after coming back from a blackout(quite frequent where I live). Below is the code for the saving mechanism only:
import pygame
from pygame.locals import *
if os.path.isfile('backup.txt'):
print('Reloading details from previous game... ')
backup = open('backup.txt', 'r')
time_a = float(backup.readline().rstrip('\n'))
team1name = backup.readline().rstrip('\n').upper()
team2name = backup.readline().rstrip('\n').upper()
team1score = int(backup.readline().rstrip('\n'))
team2score = int(backup.readline().rstrip('\n'))
currentperiod = int(backup.readline().rstrip('\n'))
team1fouls = int(backup.readline().rstrip('\n'))
team2fouls = int(backup.readline().rstrip('\n'))
possesion = bool(backup.readline().rstrip('\n'))
pygame.time.set_timer(USEREVENT + 1, 100)
while True: # Main loop
clock.tick(30)
for event in pygame.event.get():
if event.type == USEREVENT + 1: # Write to backup file
backup = open('backup.txt', 'w')
backup.write('{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n'.format(
str(time_a), team1name, team2name, str(team1score), str(team2score),
str(currentperiod), str(team1fouls), str(team2fouls), str(possesion)))
pygame.time.set_timer(USEREVENT + 1, 100)
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
backup.close()
os.remove('backup.txt')
sys.exit()
If I simulate a blackout by doing kill -9 processID, then re-run the program, nothing is wrong. But if I simulate a blackout by pulling the plug on my pi, backup.txt is empty.
I have tried changing the frequency of the saves (USEREVENT+1).
How can I get the program to save to backup.txt before an actual blackout?
Writing directly to disk instead of to the buffer solves the problem. Do:
backup.flush()
os.fsync(backup.fileno())

Resources