How do i deal with threading.Lock being super slow? - python

I wrote a singlethreaded prime-finding algorithm a while ago, and decided to try to optimise it using threading. Unfortunately, the multithreaded version is at best running 3/4 the speed of the singlethreaded one. After some research it seems that the 'threading.Lock' function is what slows it down so much. How can I improve the code?
The single-threaded code:
from math import sqrt, ceil
import time
import pickle
os.system("mode con: lines=8")
os.system("title Prime finder in Python")
primes = []
#Load primes from logprimes.data
with open("logprimes.data", "rb") as f:
primes = pickle.load(f)
if len(primes) < 4:
primes = [2, 3, 5, 7]
#Function to save results to logprimes.data
def SaveRes():
with open("logprimes.data", "wb") as f:
pickle.dump(primes, f)
return("Saved " + str(len(primes)) + " primes.")
#Function to find out if a number is a prime
def is_prime(n):
i = 0
while primes[i] < ceil(sqrt(n)):
if n % primes[i] == 0:
return False
i = i + 1
return True
starttime = time.time()
currentcheck = int(primes[len(primes) - 1])
lastsaved = time.time()
lastshowed = time.time()
#Main loop
os.system("cls")
while True:
try:
currentcheck = currentcheck + 1
if is_prime(currentcheck) == True:
primes.append(currentcheck)
if time.time() - lastshowed > 4:
print("\n\n\nTotal time: " + str(time.time() - starttime))
print("Currently checking: " + str(currentcheck))
print("Total number of primes: " + str(len(primes)))
print("Primes per sec: " + str(len(primes) / float(time.time() - starttime)))
print("Checks per sec: " + str(currentcheck / float(time.time() - starttime)))
print("Prime rarity: " + str(len(primes) / currentcheck) + "%")
lastshowed = time.time()
if time.time() - lastsaved > 300:
os.system("cls")
print(SaveRes())
lastshowed = time.time() + 2
lastsaved = time.time()
except (KeyboardInterrupt, SystemExit):
os.system("cls")
print(SaveRes())
lastsaved = time.time()
lastshowed = time.time() + 2
The multi-threaded code:
from math import sqrt, ceil
import time
import pickle
import threading
#os.system("mode con: lines=8")
os.system("title Prime finder in Python")
running = True
primes = []
threads = []
#Load primes from logprimes.data
with open("logprimes.data", "rb") as f:
primes = pickle.load(f)
if len(primes) < 4:
primes = [2, 3, 5, 7]
#Function to save results to logprimes.data
def SaveRes():
with open("logprimes.data", "wb") as f:
pickle.dump(primes, f)
return("Saved " + str(len(primes)) + " primes.")
#Function to find out if a number is a prime
def is_prime(n):
while primes[-1] < ceil(sqrt(n)): #Wait until we have enough primes to correctly deem wether or not 'n' is a prime. I know, not the most optimal solution, but it works.
pass
i = 0
while primes[i] < ceil(sqrt(n)):
if n % primes[i] == 0:
return False
i = i + 1
return True
def threadfunction(threadid, startnum = primes[-1] + 1):
global primes, running
currentcheck = startnum
with lock:
print(threadid)
while running:
if not currentcheck in primes:
if is_prime(currentcheck * (threadid + 1)):
with lock:
primes.append(currentcheck)
currentcheck += 1
exit()
startsize = len(primes)
starttime = time.time()
starthighestprime = primes[-1]
#currentcheck = int(primes[len(primes) - 1])
lastsaved = time.time()
lastshowed = time.time()
#Create threads
lock = threading.Lock()
for i in range(os.cpu_count()):
threads.append(
threading.Thread(
target=threadfunction,
args=(i,)
)
)
threads[-1].start()
#Main loop
os.system("cls")
while running and __name__ == "__main__":
try:
time.sleep(1)
if time.time() - lastshowed > 4:
print("\n\n\nTotal time: " + str(time.time() - starttime))
print("Last found prime: " + str(primes[-1]))
print("Total number of primes: " + str(len(primes)))
print("Primes per sec: " + str((len(primes) - startsize) / float(time.time() - starttime)))
print("Checks per sec: " + str((primes[-1] - starthighestprime) / float(time.time() - starttime)))
print("Prime rarity: " + str((len(primes) / primes[-1]) * 100) + "%")
lastshowed = time.time()
if time.time() - lastsaved > 300:
os.system("cls")
print(SaveRes())
lastshowed = time.time() + 2
lastsaved = time.time()
except (KeyboardInterrupt, SystemExit):
os.system("cls")
print(SaveRes())
lastsaved = time.time()
lastshowed = time.time() + 2
exit()```

Related

Socket Programming Python Server and C client

this is what i make in python server code (receiving data length from C client and then receiving image file(.jpg))
but problem is when i receiving data length error occurs "invaild base64-encoded string"
here is my servercode (Removed unnecessary functions) and when trying to run the stringData part the error occurs
import os
import socket
import cv2
import numpy
import base64
import glob
import sys
import time
import threading
from datetime import datetime
class ServerSocket:
def receiveImages(self):
cnt_str = ''
cnt = 0
try:
while True:
if (cnt < 10):
cnt_str = '000' + str(cnt)
elif (cnt < 100):
cnt_str = '00' + str(cnt)
elif (cnt < 1000):
cnt_str = '0' + str(cnt)
else:
cnt_str = str(cnt)
if cnt == 0: startTime = time.localtime()
cnt += 1
length = self.conn.recv(64)
print(length)
length1 = length.decode('utf-8')
print(length1)
stringData = self.recvall(self.conn, int(length1))
## stringData = self.conn.recv(100000)
##print(stringData)
msg = "ready"
self.conn.sendall(msg.encode())
stime = self.recvall(self.conn, 64)
print('send time: ' + stime.decode('utf-8'))
now = time.localtime()
print('receive time: ' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f'))
data = numpy.frombuffer(base64.b64decode(stringData), numpy.uint8)
decimg = cv2.imdecode(data, 1)
cv2.imshow("image", decimg)
cv2.imwrite('./' + str(self.TCP_PORT) + '_images' + str(self.folder_num) + '/img' + cnt_str + '.jpg', decimg)
cv2.waitKey(1)
if (cnt == 60 * 10):
cnt = 0
convertThread = threading.Thread(target=self.convertImage(str(self.folder_num), 600, startTime))
convertThread.start()
self.folder_num = (self.folder_num + 1) % 2
except Exception as e:
print(e)
#self.convertImage(str(self.folder_num), cnt, startTime)
self.socketClose()
cv2.destroyAllWindows()
self.socketOpen()
self.receiveThread = threading.Thread(target=self.receiveImages)
self.receiveThread.start()
def recvall(self, sock, count):
buf = b''
while count:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
def convertImage(self, fnum, count, now):
img_array = []
cnt = 0
for filename in glob.glob('./' + str(self.TCP_PORT) + '_images' + fnum + '/*.jpg'):
if (cnt == count):
break
cnt = cnt + 1
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width, height)
img_array.append(img)
file_date = self.getDate(now)
file_time = self.getTime(now)
name = 'video(' + file_date + ' ' + file_time + ').mp4'
file_path = './videos/' + name
out = cv2.VideoWriter(file_path, cv2.VideqqoWriter_fourcc(*'.mp4'), 20, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
print(u'complete')
def main():
server = ServerSocket('ServerIP', PORT)
if __name__ == "__main__":
main()
what could it be the problems? in my expectation when decode the string data it can be the problem that C client encode causes problem

Python multiprocessing shared memory without copy

I'm currently working on a project for fun, involving calculating way too many numbers of the Fibonacci sequence. Thing is, I want it to go fast and I also don't want to loose too much progress if I have to do an update or have a computer issues....
So I over-engineered that, and I am currently looking to implement it with multiprocessing, but everywhere I look the only way to share memory in that case is to make a duplicate of it and that takes about an hour for (Yeah I have very big numbers)
Is there any way to share a dictionary with multiprocessing without making a copy of it?
Here is the code, currently with my last implementation using threading instead of using multiprocessing. (ignore the bad timekeeping of this, i'll fix it later)
import threading
import time
def printProgressBar(iteration, total, prefix="", suffix="", decimals=1, length=100, fill="█", printEnd="\r"):
"""
Call in a loop to create terminal progress bar
#params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + "-" * (length - filledLength)
print(
f"\r{prefix} |{bar}| {percent}% {suffix} {time.strftime('%dd %H:%M:%S', time.gmtime(time.time() - start_time - 86400)).replace('31d', '0d')}",
end=printEnd,
)
# Print New Line on Complete
if iteration == total:
print()
dict47 = {0: 0, 1: 1, 2: 1}
dict47[0] = 2
def fibSequence(n):
if n not in dict47:
dict47[n] = fibSequence(n - 1) + fibSequence(n - 2)
if n > dict47[0]:
dict47[0] = n
if n > 5 and not ((n - 3) % (iterations // 100) == 0) and not ((n - 2) % (iterations // 100) == 0):
dict47.pop(n - 3, None)
return dict47[n]
def makeBackup(start, num, total):
x = threading.Thread(target=writeBackup, args=(num,), daemon=False)
y = threading.Thread(target=writeBackup, args=(num - 1,), daemon=False)
x.start()
y.start()
x.join()
y.join()
time.sleep(1)
print(
f'{num/10000000}% done after {time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start - 86400)).replace("31d", "0d")}'
)
timings = open("times.txt", "a")
timings.write(str(int(time.time() - start)) + "\n")
timings.close()
def writeBackup(num):
file = open(f".temp/fib{num}.txt", "a")
file.write(str(num) + " : " + str(dict47[num]))
file.close()
dict47.pop(num, None)
def loadDict():
from pathlib import Path
maximum = 0
for n in range(1, 100):
if Path(f".temp/fib{n*10000000}.txt").is_file():
maximum = n * 10000000
print("Maximum number found:", maximum)
if maximum != 0:
file = open(f".temp/fib{maximum}.txt", "r")
temp = "".join(file.readlines())
dict47[maximum] = int(temp.lstrip(str(maximum) + " : "))
file.close()
file = open(f".temp/fib{maximum - 1}.txt", "r")
temp = "".join(file.readlines())
dict47[maximum - 1] = int(temp.lstrip(str(maximum - 1) + " : "))
file.close()
dict47[0] = maximum
print("Dictionary loaded at ", maximum)
else:
print("No dictionary found, starting from scratch")
if __name__ == "__main__":
try:
timings = open("times.txt", "r")
lastTime = int(timings.readlines()[-1])
start_time = time.time() - lastTime
timings.close()
except:
start_time = time.time() + 86400
print("Start duration:", time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start_time)).replace("31d", "0d"))
try:
iterations = int(input("Enter the number of iterations: "))
except:
iterations = 1000000000
print(iterations, "iterations will be performed")
loadDict()
num = dict47[0]
while num < iterations:
if num == 2:
num += 248
else:
num += 250
fibSequence(num)
if num % 1000 == 0:
printProgressBar(num, iterations, prefix="Progress:", suffix="Complete", length=100)
if num % (iterations // 100) == 0:
save = threading.Thread(
target=makeBackup,
args=(start_time, num, iterations),
daemon=False,
)
save.start()
file = open("fib.txt", "a")
file.write(str(iterations) + " : " + str(fibSequence(iterations)) + "\n")
file.close()
try:
save.join()
except:
print("No save thread running, exiting...")

How to print the time of execution PYTHON

I have this code, but I want to print the time that a specific part of it takes.
The block of code that I want to know the time is between:
def TSP(lista2d):
import copy
origen = input("Ciudad de origen: ")
resultado = [int(origen)]
iteracion, indicador = int(origen) - 1, 0
distancia, copia = [], copy.deepcopy(lista2d)
for j in range(1, len(lista2d)):
for x in range(len(lista2d)):
lista2d[x][iteracion] = 999
distancia.append(min(lista2d[iteracion]))
for i in range(len(lista2d)):
if min(lista2d[iteracion]) == lista2d[iteracion][i]:
indicador = i
lista2d[indicador][iteracion] = 999
resultado.append(indicador + 1)
iteracion = indicador
resultado.append(int(origen))
a = copia[resultado[-2] - 1][int(origen) - 1]
distancia.append(a)
print("El camino mas corto: " + str(resultado) + "\nCosto total: " + str(sum(distancia)))
TSP([[999,100,150,140,130,120,78,150,90,200,180,190,160,135,144,300,60,77,87,90],
[100,999,200,180,190,160,135,144,90,150,140,130,120,78,300,160,88,99,87,95],
[150,200,999,167,156,169,123,134,156,177,155,188,176,143,192,146,170,152,176,122],
[140,180,167,999,190,198,213,321,252,123,234,111,112,114,167,189,203,205,234,300],
[130,190,156,190,999,333,300,178,167,143,200,111,156,267,299,152,100,90,97,99],
[120,160,169,198,333,999,480,389,412,500,253,222,333,378,287,273,266,255,199,201],
[78,135,123,213,300,480,999,140,150,143,177,194,166,200,181,154,177,133,122,109],
[150,144,134,321,178,389,140,999,149,129,129,136,156,177,141,186,175,153,133,122],
[90,90,156,252,167,412,150,149,999,89,82,83,60,124,59,78,89,99,100,123],
[200,150,177,123,143,500,143,129,89,999,99,200,254,233,211,197,183,154,167,169],
[180,140,155,234,200,253,177,129,82,99,999,77,88,89,289,222,311,471,122,109],
[190,130,188,111,111,222,194,136,83,200,77,999,91,90,93,106,132,100,98,35],
[160,120,176,112,156,333,166,156,60,254,88,91,999,102,103,107,111,113,200,101],
[135,78,143,114,267,378,200,177,124,233,89,90,102,999,77,79,201,166,173,102],
[144,300,192,167,299,287,181,141,59,211,289,93,103,77,999,55,103,105,101,201],
[300,160,146,189,152,273,154,186,78,197,222,106,107,79,55,999,76,78,84,92],
[60,88,170,203,100,266,177,175,89,183,311,132,111,201,103,76,999,93,102,29],
[77,99,152,205,90,255,133,153,99,154,471,100,113,166,105,78,93,999,88,65],
[87,87,176,234,97,199,122,133,100,167,122,98,200,173,101,84,102,88,999,333],
[90,95,122,300,99,201,109,122,123,169,109,35,101,102,201,92,29,65,333,999]])
You can use 'time.time()' for example
Start_time = time.time()
End_time = time.time()
Diff_time = End_time()-Start_time()

Calculating the amount of time left until completion

I am wondering how to calculate the amount of time it would take to example:
Complete a brute force word list.
I know how to use the time function and measure in time,
but the problem is i need to find out how long it would take in the program itself...
Here is the code i made this yesterday
import itertools, math
import os
Alphabet = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") # Add or remove whatevs you think will be in the password you're cracking (example, [symbols])
counter = 1
CharLength = 1
range_num = int(raw_input("Enter range: "))
stopper = range_num + 1
filename = "bruteforce_%r.txt" % (range_num)
f = open(filename, 'a')
#n_1 = len(Alphabet)
#n_2 = n_1 - 1 # <-- total useless peice of garbage that could of been great in vurtual life
#n_3 = '0' * n_2
#n = '1' + n_3
x = range_num
y = len(Alphabet)
amount = math.pow(y, x)
total_items = math.pow(y, x)
for CharLength in range(range_num, stopper):
passwords = (itertools.product(Alphabet, repeat = CharLength))
for i in passwords:
counter += 1
percentage = (counter / total_items) * 100
amount -= 1
i = str(i)
i = i.replace("[", "")
i = i.replace("]", "")
i = i.replace("'", "")
i = i.replace(" ", "")
i = i.replace(",", "")
i = i.replace("(", "")
i = i.replace(")", "")
f.write(i)
f.write('\n')
print "Password: %r\tPercentage: %r/100\tAmount left: %r" % (i, int(percentage), amount)
if i == '0'* range_num:
print "*Done"
f.close()
exit(0)
else:
pass
This is my timer function i managed to make
#import winsound # Comment this out if your using linux
import os
import time
from sys import exit
print "This is the timer\nHit CTRL-C to stop the timer\nOtherwise just let it rip untill the time's up"
hours = int(raw_input('Enter the hours.\n>>> '))
os.system('clear') # Linux
#os.system('cls') # Windows
minutes = int(raw_input('Enter the minutes.\n>>> '))
os.system('clear') # linux
#os.system('cls') # Windows
seconds = int(raw_input('Enter the seconds.\n>>> '))
os.system('clear') # Linux
#os.system('cls') # Windows
stop_time = '%r:%r:%r' % (hours, minutes, seconds)
t_hours = 00
t_minutes = 00
t_seconds = 00
while t_seconds <= 60:
try:
os.system('clear') # Linux
#os.system('cls') # Windows
current_time = '%r:%r:%r' % (t_hours, t_minutes, t_seconds)
print current_time
time.sleep(1)
t_seconds+=1
if current_time == stop_time:
print "// Done"
#winsound.Beep(500,1000)
#winsound.Beep(400,1000)
break
elif t_seconds == 60:
t_minutes+=1
t_seconds=0
elif t_minutes == 60:
t_hours+=1
t_minutes = 00
except KeyboardInterrupt:
print "Stopped at: %r:%r:%r" % (t_hours, t_minutes, t_seconds)
raw_input("Hit enter to continue\nHit CTRL-C to end")
try:
pass
except KeyboardInterrupt:
exit(0)
Now i just cant figure out how to make this again but to calculate how long it will take rather than how long it is taking...
You cannot predict the time a script is going to take.
Firstly because two machines wouldn't run the script in the same time, and secondly, because the execution time on one machine can vary from on take to another.
What you can do, however, is compute the percentage of execution.
You need to figure out, for example, how many iterations your main loop will do, and calculate at each iteration the ratio current iteration count / total number of iterations.
Here is a minimalist example of what you can do:
n = 10000
for i in range(n):
print("Processing file {} ({}%)".format(i, 100*i//n))
process_file(i)
You can take it further and add the time as an additional info:
n = 10000
t0 = time.time()
for i in range(n):
t1 = time.time()
print("Processing file {} ({}%)".format(i, 100*i//n), end="")
process_file(i)
t2 = time.time()
print(" {}s (total: {}s)".format(t2-t1, t2-t0))
The output will look like this:
...
Processing file 2597 (25%) 0.2s (total: 519.4s)
Processing file 2598 (25%) 0.3s (total: 519.7s)
Processing file 2599 (25%) 0.1s (total: 519.8s)
Processing file 2600 (25%)
This is my implementation, which returns time elapsed, time left, and finish time in H:M:S format.
def calcProcessTime(starttime, cur_iter, max_iter):
telapsed = time.time() - starttime
testimated = (telapsed/cur_iter)*(max_iter)
finishtime = starttime + testimated
finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time
lefttime = testimated-telapsed # in seconds
return (int(telapsed), int(lefttime), finishtime)
Example:
import time
import datetime as dt
start = time.time()
cur_iter = 0
max_iter = 10
for i in range(max_iter):
time.sleep(5)
cur_iter += 1
prstime = calcProcessTime(start,cur_iter ,max_iter)
print("time elapsed: %s(s), time left: %s(s), estimated finish time: %s"%prstime)
Output:
time elapsed: 5(s), time left: 45(s), estimated finish time: 14:28:18
time elapsed: 10(s), time left: 40(s), estimated finish time: 14:28:18
time elapsed: 15(s), time left: 35(s), estimated finish time: 14:28:18
....
You will never ever be able to know exactly how long it is going to take to finish. The best you can do is calculate was percentage of the work you have finished and how long that has taken you and then project that out.
For example if you are doing some work on the range of numbers from 1 to 100 you could do something such as
start_time = get the current time
for i in range(1, 101):
# Do some work
current_time = get the current time
elapsed_time = current_time - start_time
time_left = 100 * elapsed_time / i - elapsed_time
print(time_left)
Please understand that the above is largely pseudo-code
The following function will calculate the remaining time:
last_times = []
def get_remaining_time(i, total, time):
last_times.append(time)
len_last_t = len(last_times)
if len_last_t > 5:
last_times.pop(0)
mean_t = sum(last_times) // len_last_t
remain_s_tot = mean_t * (total - i + 1)
remain_m = remain_s_tot // 60
remain_s = remain_s_tot % 60
return f"{remain_m}m{remain_s}s"
The parameters are:
i : The current iteration
total : the total number of iterations
time : the duration of the last iteration
It uses the average time taken by the last 5 iterations to calculate the remaining time. You can the use it in your code as follows:
last_t = 0
iterations = range(1,1000)
for i in iterations:
t = time.time()
# Do your task here
last_t = time.time() - t
get_remaining_time(i, len(iterations), last_t)

Python For loop repeating endlessly

I'm currently writing a program to check speeds of cars and their license plates, and I want to repeat the function that does this x number of times, the problem I'm having though is that the function is repeating endlessly and is not adhering to the number of times I want it to loop.
Here is what I have so far:
if correctMatch:
pass
else:
with open('Camera Output.txt', 'a') as f:
print("DATA RECORDED TO: Camera Output.txt")
exactTime2 = datetime.now()
f.write("{} has a non-standard license plate and has been recorded at {}.".format(licensePlate,
exactTime2) + "\n")
f.write("---------------------------------------------------------\n")
if speedCarMph > 60:
with open('Camera Output.txt', 'a') as f:
print("DATA RECORDED TO: Camera Output.txt")
exactTime= datetime.now()
f.write("{} was travelling at {}MPH, recorded at {} and has broken the law.".format(licensePlate,
speedCarMph, exactTime) + "\n")
f.write("----------------------------------------------------------\n")
licensePlateCheck()
for x in range(N):
repeatNum = 0
while repeatNum < 10:
repeatNum += 1
licensePlateCheck()
if repeatNum == 10:
print("Completed generation")
I also attempted to use a thread but that didn't work. If you need any more of the code, just ask.
The full code is here (excluding an unrelated function and the function choice):
import re
import threading
from queue import Queue
def licensePlateCheck():
camInput1 = datetime.now()
print(camInput1)
print("Car is travelling...")
time.sleep(0.1)
print("Car has passed cam2")
camInput2 = timedelta(seconds = random.uniform(5, 10))
distance = 200
duration = camInput2.total_seconds()
print("Time Delta is equal to: {0}".format(duration))
speedCarMs = distance/duration
print("Car is travelling in m/s at: {0}".format(speedCarMs))
speedCarMph = 2.237*speedCarMs
print("Car is travelling in MPH at: {0}".format(speedCarMph))
licenseCharNum = randint(2,9)
licensePlate = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(licenseCharNum))
licensePlateLayout = re.compile('[A-Z][A-Z]\d\d[A-Z][A-Z][A-Z]')
correctMatch = licensePlateLayout.match(licensePlate)
if correctMatch:
pass
else:
with open('Camera Output.txt', 'a') as f:
print("DATA RECORDED TO: Camera Output.txt")
exactTime2 = datetime.now()
f.write("{} has a non-standard license plate and has been recorded at {}.".format(licensePlate,
exactTime2) + "\n")
f.write("----------------------------------------------------------\n")
if speedCarMph > 60:
with open('Camera Output.txt', 'a') as f:
print("DATA RECORDED TO: Camera Output.txt")
exactTime= datetime.now()
f.write("{} was travelling at {}MPH, recorded at {} and has broken the law.".format(licensePlate,
speedCarMph, exactTime) + "\n")
f.write("----------------------------------------------------------\n")
licensePlateCheck()
for x in range(N):
repeatNum = 0
while repeatNum < 10:
repeatNum += 1
licensePlateCheck()
if repeatNum == 10:
print("Completed generation")
In that case you have unnecessary used while loop:)
for x in range(N): // will iterate x times
licensePlateCheck()
print("Completed generation")
With nested while loop, your method would execute:
x * 10 times:
x - for loop
10 - while loop
Both For and While are correct, the choice is up to you.

Categories

Resources