breaking a loop in the middle python - python-3.x

i am trying to have a loop that keeps functioning until something is inputted which will break the loop. However if i put in 'stop = input()' in the loop then it has to go through that first before doing anything else. my code is like this: (it uses some minecraft commands. basically im trying to make a block move down a 20X20 square and have it be able to stop in the middle on command)
from mcpi import minecraft
mc=minecraft.Minecraft.create()
from time import sleep
pos=mc.player.getTilePos
x=pos.x
y=pos.y
z=pos.z
mc.setBlocks(x-10,y,z+30,x+10,y+20,z+30,49)
BB=0
while BB<20:
BB=BB+1
sleep(.7)
mc.setBlock(x,y+(20-BB),z+30,35)
mc.setBlock(x,y+(21-BB),z+30,49)
stop=input()
if stop=='stp':
break
how do i keep the loop going until someone inputs 'stp'? because currently it will move one block then stop and wait until i input something. The loop works if i take out the last three lines.

Whenever you run into input() in your code, Python will stop until it receives an input. If you're running the script in your console, then pressing Ctrl+C will stop execution of the program. (I'll assume you are, because how else would you be able to input 'stp'?)

You can run your logic in a different thread and signal this thread whenever you get an input.
from mcpi import minecraft
import threading
mc=minecraft.Minecraft.create()
from time import sleep
pos=mc.player.getTilePos
stop = False
def play():
x=pos.x
y=pos.y
z=pos.z
mc.setBlocks(x-10,y,z+30,x+10,y+20,z+30,49)
BB=0
while BB<20:
BB=BB+1
sleep(.7)
mc.setBlock(x,y+(20-BB),z+30,35)
mc.setBlock(x,y+(21-BB),z+30,49)
if stop:
break
t = threading.Thread(target=play)
t.start()
while True:
s = input()
if s == 'stp':
stop = True # the thread will see that and act appropriately

I know this is kind of old but I programed something similar earlier so here is a quick adaptation to your needs, hope you don't need it though xD
from mcpi.minecraft import Minecraft
from threading import Thread
from time import sleep
mc = Minecraft.create()
class Placer(Thread):
def __init__(self):
self.stop = False
Thread.__init__(self)
def run(self):
x, y, z = mc.player.getPos()
mc.setBlocks(x - 10, y, z + 30, x + 10, y + 20, z + 30, 49)
for i in range(20, -1, -1):
mc.setBlock(x, y + i, z + 30, 35)
mc.setBlock(x, y + i + 1 - 1, z + 30, 49)
sleep(0.7)
if self.stop:
break
placer = Placer()
placer.start()
while True:
text = input(": ")
if text == "stp":
placer.stop = True

Related

Python 3 not opening in console anymore, but in Powershell (Windows 11)

I have previously used this StackOverflow question to write the following code to my program:
import os
os.system('mode con: cols=20 lines=5')
When I double click this Python script from File Explorer, this used to open the console window (command window I believe) in the specified size. However, since recently, it is not doing that anymore. Instead, it now opens Windows PowerShell, and the resizing doesn't function.
My desired result is to resize the window that my print statements are printed to. Also, I should be able to resize the window after making some new print statements. For full code, see below. If I should reduce the code for readability, please let me know.
import os
import math
import sys
# defining round_half_up
def round_half_up(n, decimals=0):
multiplier = 10 ** decimals
return math.floor(n * multiplier + 0.5) / multiplier
def main():
IDLE = "idlelib" in sys.modules
if not IDLE:
os.system('mode con: cols=20 lines=5')
while True: # get some input until it is valid
try:
points = float(input("Total points: "))
if points==int(points):
points = int(points)
break
except ValueError:
print("That's not a number.\n")
while True: # get some more input while it is valid
try:
grade = int(input("Maximum grade: "))
break
except ValueError:
print("That's not a whole number.\n")
if not IDLE:
# calculate the size of the window
cols = 5 + 4*(4+4+10) -10
lines = math.ceil(points) + 5
# apply the new size of the window
os.system('mode con: cols={:d} lines={:d}'.format(cols, lines))
# print all the results
for i in range(math.ceil(points)):
lst = [0.]*8
for j in range(4):
lst[j*2] = i+j*0.25
lst[j*2+1] = round_half_up((i+j*0.25)*grade/points, 1)
print(("{:5.2f} -->{:4.1f}{:10.2f} -->{:4.1f}{:10.2f}" + \
"-->{:4.1f}{:10.2f} -->{:4.1f}").format(*lst))
print("{:5.2f} -->{:4.1f}".format(math.ceil(points), grade))
print()
if points==int(points):
tickets = "90% is either {:.2f}/{:d} or {:.1f}/{:d}"
else:
tickets = "90% is either {:.2f}/{:.1f} or {:.1f}/{:d}"
print(tickets.format(0.9*points, points, 0.9*grade, grade))
print()
if __name__=='__main__':
while True: # keep window open and/or get new inputs until enter is pressed
main()
again = input("Type anything to start again, or just press enter to close:")
if again == "":
break

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')

Python 3.6 Bitonic Sort with Multiprocessing library and multiple processes

I am trying to implement bitonic with the python multiprocessing library and a shared resource array that will be sorted at the end of the program.
The problem I am running into is that when I run the program, I get an prompt that asks "Your program is still running! Are you sure you want to cancel it?" and then when I click cancel N - 1 times (where N is the amount of processes I am trying to spawn) then it just hangs.
When this is run from the command line, it just outputs the unsorted array. Of course, I expect it to be sorted at the program's finish.
I've been using this resource to try and get a firm grasp on how I can mitigate my errors but I haven't had any luck, and now I am here.
ANY help would be appreciated, as I really don't have anywhere else to turn to.
I wrote this using Python 3.6 and here is the program in its entirety:
from multiprocessing import Process, Array
import sys
from random import randint
# remember to move this to separate file
def createInputFile(n):
input_file = open("input.txt","w+")
input_file.write(str(n)+ "\n")
for i in range(n):
input_file.write(str(randint(0, 1000000)) + "\n")
def main():
# createInputFile(1024) # uncomment this to create 'input.txt'
fp = open("input.txt","r") # remember to read from sys.argv
length = int(fp.readline()) # guaranteed to be power of 2 by instructor
arr = Array('i', range(length))
nums = fp.read().split()
for i in range(len(nums)):
arr[i]= int(nums[i]) # overwrite shared resource values
num_processes = 8 # remember to read from sys.argv
process_dict = dict()
change_in_bounds = len(arr)//num_processes
low_b = 0 # lower bound
upp_b = change_in_bounds # upper bound
for i in range(num_processes):
print("Process num: " + str(i)) # are all processes being generated?
process_dict[i] = Process(target=bitonic_sort, args=(True, arr[low_b:upp_b]) )
process_dict[i].start()
low_b += change_in_bounds
upp_b += change_in_bounds
for i in range(num_processes):
process_arr[i].join()
print(arr[:]) # Print our sorted array (hopefully)
def bitonic_sort(up, x):
if len(x) <= 1:
return x
else:
first = bitonic_sort(True, x[:len(x) // 2])
second = bitonic_sort(False, x[len(x) // 2:])
return bitonic_merge(up, first + second)
def bitonic_merge(up, x):
# assume input x is bitonic, and sorted list is returned
if len(x) == 1:
return x
else:
bitonic_compare(up, x)
first = bitonic_merge(up, x[:len(x) // 2])
second = bitonic_merge(up, x[len(x) // 2:])
return first + second
def bitonic_compare(up, x):
dist = len(x) // 2
for i in range(dist):
if (x[i] > x[i + dist]) == up:
x[i], x[i + dist] = x[i + dist], x[i] #swap
main()
I won't go into all the syntax errors in your code since I am sure your IDE tells you about those. The problem that you have is that you are missing an if name==main. I changed your def main() to def sort() and wrote this:
if __name__ == '__main__':
sort()
And it worked (after solving all the syntax errors)

Stopwatch program

I need to make a stop watch program, I need Start, Stop, Lap, Reset and Quit functions. The program needs print elapsed times whenever the Stop or Lap key is pressed. When the user chooses to quit the program should write a log file containing all the timing data (event and time) acquired during the session in human readable format.
import os
import time
log = ' '
def cls():
os.system('cls')
def logFile(text):
logtime = time.asctime( time.localtime(time.time()) )
f = open('log.txt','w')
f.write('Local current time :', logtime, '\n')
f.write(text, '\n\n')
f.close()
def stopWatch():
import time
p = 50
a = 0
hours = 0
while a < 1:
cls()
for minutes in range(0, 60):
cls()
for seconds in range(0, 60):
time.sleep(1)
cls()
p +=1
print ('Your time is: ', hours, ":" , minutes, ":" , seconds)
print (' H M S')
if p == 50:
break
hours += 1
stopWatch()
I have it ticking the time, however they way I have it wont allow me to stop or lap or take any input. I worked to a few hours to find a way to do it but no luck. Any Ideas on how im going to get the functions working?

how to make two mapper functions run parallel?

I read this python documentation on multiprocessing.
But I had a requirement like following:
from multiprocessing import Pool
import time
def f(x):
print(x)
time.sleep(100000000000000);
return x*x
def f2(x):
print('**' + str(x) + '**')
time.sleep(100000000000000);
return x*x*x;
if __name__ == '__main__':
p = Pool(5)
print(p.map(f, [1, 2, 3]))
print(p.map(f2,[1,2,3]))
I have a use case where the function f is blocking(in my case it listens to a rabbitmq queue, so it should be blocking. I used a long time delay-100000000000000 to imply the infinite time blocking).
I have simulated blocking with the time.delay here.
but the need is i want the f2 (which is different from f) to start and run parallel. At present it does not even go to f2 as f itself blocks.
Can someone please give some guidance on how to make f and f2 start parallely despite the fact being f and f2 are both blocking.
Update:
Seems like i found a way, but puzzled
from multiprocessing import Pool
import time
def f(x):
print(x)
time.sleep(100000000000000);
return x*x
def f2(x):
print('**' + str(x) + '**')
time.sleep(100000000000000);
return x*x*x;
if __name__ == '__main__':
p = Pool(5)
res = p.apply_async(f, [2])
res = p.apply_async(f2,[4])
res.get()
how even after reassigning res1 it works and it invokes even f ?
Your approach doesn't work since first pool must complete to be able to print the result before the second pool. So the print kind of blocks the second pool from starting.
I used a thread pool to start both wrappers simultaneously, and I get the results asynchronously. I had to make a loop instead of the big sleep because python complained that sleep was too large. But amounts to the same thing.
In my case, there are printouts of 1,2,3 1,2,3 at once. And if I set the wait loop to a reasonable value I even get some correct results.
from multiprocessing import Pool
import concurrent.futures
import time
sleep_times = 1000000
def f(x):
print(x)
for i in range(sleep_times):
time.sleep(10)
return x*x
def f2(x):
print('**' + str(x) + '**')
for i in range(sleep_times):
time.sleep(10)
return x*x*x;
def fwrap(l):
p = Pool(len(l))
return(p.map(f, l))
def fwrap2(l):
p = Pool(len(l))
return(p.map(f2, l))
if __name__ == '__main__':
jr = dict()
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
jr[executor.submit(fwrap, (1, 2, 3))] = "f"
jr[executor.submit(fwrap2, (1, 2, 3))] = "f2"
for future in concurrent.futures.as_completed(jr):
ident = jr[future]
print(ident,future.result())
output (when sleep loop reduced to 1 to avoid waiting for too long)
1
**1**
2
**2**
**3**
3
there it waits a while (blocked by "processing time") then:
('f', [1, 4, 9])
('f2', [1, 8, 27])

Resources