ProgressBar same timing as a function - python-3.x

I want the progress bar to be the same timing with a function, starts when it starts and stop when it is finished
I tried using while loops but it didn't work out.
def clean(path):
for path in paths:
try:
rmtree(path)
except OSError:
pass
while clean is True:
for i in range(1):
sys.stdout.write("%s" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width + 1))
for i in range(toolbar_width):
sleep(0.1) # do real work here
# update the bar
sys.stdout.write("█████")
sys.stdout.flush()
sys.stdout.write("\nDone Cleaning\n")
I expect the progress bar to print it out according to the clean() function
when it is running it will run and when it is done it stops.

You are missing a ":" after your "True" statement. Your code is otherwise correct. Just make sure you check over your work! It should look like:
def clean(path):
for path in paths:
try:
rmtree(path)
except OSError:
pass
while clean is True:
for i in range(1):
sys.stdout.write("%s" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width + 1))
for i in range(toolbar_width):
sleep(0.1) # do real work here
# update the bar
sys.stdout.write("█████")
sys.stdout.flush()
sys.stdout.write("\nDone Cleaning\n")

Related

pyautogui is delayed in .png searches/ going to next line of code too soon

Okay I've gotten pretty far since I started this but I've been wondering about a few things I'd like to improve on.
So When the dell.com/support pops up it takes about 10 seconds for it to figure out where to click. (Lines 31-35) this ends up being an issue because sometimes the next part of the code starts running.
For example while #drivers and downloads is still being searched for it jumps to (ctrl+f "show all")
What can I do to decrease the delays? without just adding in more time.sleep(x) is there something I can set up for a wait until XYZ
"""
Pip install list:
autogui
pyperclip
pillow
"""
import subprocess
import pyperclip
import re
import os
import pyautogui
import time
SerialNumber = 'wmic bios get serialnumber'
result = subprocess.getoutput(SerialNumber)
SerialResult = (result.strip("SerialNumber"))
print(re.sub("[^a-zA-Z0-9]+", "", SerialResult))
pyperclip.copy(re.sub("[^a-zA-Z0-9]+", "", SerialResult))
os.system("start chrome.exe --new-window dell.com/support")
screenWidth, screenHeight = pyautogui.size() #gets the size of Primary Monitor
currentMouseX, currentMouseY = pyautogui.position() #gets the XY position of mouse
print(" X: ", currentMouseX, "Y: ", currentMouseY,"\n", "Width:",screenWidth, "Height:", screenHeight)
#searchbar
SearchBarLocation = pyautogui.locateOnScreen('SearchBar.PNG')
pyautogui.moveTo(SearchBarLocation)
time.sleep(3)
pyautogui.click()
pyautogui.hotkey('ctrl', 'v')
pyautogui.press('enter')
print(1)
#drivers and download
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('drivers & downloads')
DriversAndDownloadsLocation = pyautogui.locateOnScreen('DriversAndDownloads.PNG')
time.sleep(3)
pyautogui.moveTo(DriversAndDownloadsLocation)
pyautogui.click()
print(2)
#find drivers
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Find drivers')
time.sleep(1)
FindDriversLocation = pyautogui.locateOnScreen('FindDrivers.PNG')
time.sleep(3)
pyautogui.moveTo(FindDriversLocation)
pyautogui.click()
print(3)
#show all
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Show all')
time.sleep(1)
ShowAllLocation = pyautogui.locateOnScreen('ShowAll.png')
time.sleep(3)
pyautogui.moveTo(ShowAllLocation)
pyautogui.click()
print(4)
#Dell Update
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('dell command | update application')
time.sleep(1)
DellUpdateLocation = pyautogui.locateOnScreen('DellUpdate.PNG')
time.sleep(3)
pyautogui.moveTo(DellUpdateLcation)
print(5)
#Download
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Download')
time.sleep(1)
DownloadLocation = pyautogui.locateOnScreen('Download')
time.sleep(3)
pyautogui.moveTo(DownloadLocation)
There are a few things you can do to make locateOnScreen run quicker. You can designate a region to search in and you can toggle the grayscale flag to be True.
If SearchBar.png always appears in the same area of the screen, you can use a tool in pyautogui to record the co-ordinates. If you open a python shell and write
import pyautogui
pyautogui.mouseInfo()
An application called MouseInfo will open up that will assist in recording the co-ordinates. When designating a region for location onscreen, the format is (left, top, width, height).
For example, if you knew SearchBar.png was reliably always appearing at 1142, 721 and was 160 pixels wide and 80 pixels high, you could use do this:
pyautogui.locateOnScreen('SearchBar.png', region=(1142, 721, 160, 80))
Optionally, you can also toggle grayscale onto that call to make it faster.
pyautogui.locateOnScreen('SearchBar.png', region=(1142, 721, 160, 80), grayscale=True)
If you NEED SearchBar.png to continue your script, and the process breaks without finding it, you can implement a technique called Busy waiting. Basically, keep checking for a condition and do not proceed until it is met. The implementation of that would look something like this:
timer = 0
timeout_time = 60
search_bar_location= pyautogui.locateOnScreen('SearchBar.png')
while search_bar_location is None:
if timer > timeout_time:
print('Could not find the search bar in 60 seconds')
exit(1)
time.sleep(1)
search_bar_location = pyautogui.locateOnScreen('SearchBar.png')
timer += 1
# Searchbar is available if the code gets here
pyautogui.moveTo(search_bar_location)
...
It's generally good practice to not busy wait forever, that's why I've added the timer variables to exit the script after 60 seconds of busy waiting.

How can I make an interactive Label with Tkinter in Python

I am trying to make an idlegame using Tkinter, but I don't know how to keep the Label that shows the amount of money updating.
I tried to make the label update using a while loop but the program didn't load the window without a mainloop() properly.
I've put w.mainloop() in the loop, but now it doesn't repeat anymore. (w=Tk())
def money():
File=open('./assets/save/money.txt','r')
moneynow=File.read()
File.close()
try:
if int(moneynow) >> 0 or int(moneynow) == 0:
do='nothing'
except:
File=open('./assets/save/money.txt','w')
File.write('0')
File.close()
w.destroy()
text1=Label(w,text='You currently have',bg='#CEE3F6',font=('arial black',10),fg='#820038')
text1.place(x=250,y=5)
text2=Label(w,text='$',bg='#CEE3F6',font=('arial black',10),fg='#820038')
text2.place(x=298,y=70)
#Interactive GUI
while True:
money()
File=open('./assets/save/money.txt','r')
moneyamount=File.read()
File.close()
moneydisplay=Label(w,text=moneyamount,bg='#CEE3F6',font=('impact',40),fg='#FFCA4F',pady=-3)
moneydisplay.place(x=289,y=25,height=45)
w.mainloop()
Expected result: The loop keeps continuing.
Actual result: The loop doesn't repeat itself, since the compiler stops after w.mainloop().
mainloop is loop which run all time till you close window. You have to use after(time, function_name) to send it to mainloop and it will run it after selecte time - this way it will repeate function like in own loop.
from tkinter import *
def update_money():
with open('./assets/save/money.txt') as f:
moneynow = f.read()
try:
if int(moneynow) < 0:
with open('./assets/save/money.txt', 'w') as f:
f.write('0')
w.destroy()
except:
print('Cant convert')
w.destroy()
moneydisplay['text'] = moneynowe
w.after(1000, update_money) # run again after 1000ms (1s)
# --- main --
w = Tk()
text1 = Label(w, text='You currently have')
text1.pack()
text2 = Label(w, text='$')
text2.pack()
moneydisplay = Label(w, text="") # empty label, I will put text later
moneydisplay.pack()
update_money() # put text first time
w.mainloop()

Interact with python REPL from python script

I want to find (or make) a python script that reads a different python script line by line and prints the commands executed and the output right there after.
Suppose you have a python script, testfile.py as such:
print("Hello world")
for i in range(3):
print(f"i is: {i}")
Now, I want a different python script that parses the testfile.py and outputs the following:
print("Hello world")
## Hello world
for i in range(3):
print(f"i is: {i}")
## i is: 0
## i is: 1
## i is: 2
Any suggestions on existing software or new code on how to achieve this is greatly appreciated!
Attempts / concept code:
Running ipython from python:
One of the first thoughts were to run ipython from python using subprocess:
import subprocess
import re
try:
proc = subprocess.Popen(args=["ipython", "-i"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
# Delimiter to know when to stop reading
OUTPUT_DELIMITER = ":::EOL:::"
# Variable to contain the entire interaction:
output_string = ""
# Open testfile.py
with open("testfile.py") as file_:
for line in file_:
# Read command
cmd = line.rstrip()
# Add the command to the output string
output_string += cmd + "\n"
proc.stdin.write(f"{cmd}\n")
# Print the delimiter so we know when to end:
proc.stdin.write('print("{}")\n'.format(OUTPUT_DELIMITER))
proc.stdin.flush()
# Start reading output from ipython
while True:
thisoutput = proc.stdout.readline()
thisoutput = thisoutput.rstrip()
# Now check if it's the delimiter
if thisoutput.find(OUTPUT_DELIMITER) >= 0:
break
output_string += thisoutput + "\n"
except Exception as e:
proc.stdout.close()
proc.stdin.close()
raise
proc.stdout.close()
proc.stdin.close()
print("-" * 4 + "START OUTPUT" + "-" * 4)
print(output_string)
print("-" * 4 + "END OUTPUT" + "-" * 4)
In this approach, the problem becomes indented blocks, like the for loop.
Ideally something like this would work using just plain python (and not ipython).
code.InteractiveConsole.interact does exactly what is asked.
This is not exactly what you wanted, but it's close. trace module does something very similar.
so.py:
print("Hello world")
for i in range(3):
print(f"i is: {i}")
python -m trace --trace so.py
--- modulename: so, funcname: <module>
so.py(1): print("Hello world")
Hello world
so.py(3): for i in range(3):
so.py(4): print(f"i is: {i}")
i is: 0
so.py(3): for i in range(3):
so.py(4): print(f"i is: {i}")
i is: 1
so.py(3): for i in range(3):
so.py(4): print(f"i is: {i}")
i is: 2
so.py(3): for i in range(3):

if __name__==function_name()

Why does python calls the function which is checked as name== function_name()
When i run this program
In this program
def game():
print("1")
return("2")
def main():
print("game over")
if __name__==game():
print("3")
else:
print("4")
the output is:
1 # here the method game() is called and why is it so?
4
Can anyone explain the reason behind this
Thank you in advance
game() returns the string "2" that is not equal to the value of __name__, the variable which refers to the name of in scope module.
Your code is not easy to read: I suggest you to add blank lines to make clear the distinction among different function. Here is a modified version that should clarify what happens when you execute it.
def game():
print("I'm: " + __name__ + " executing game()")
print("1")
print("I'm going to return 2")
return("2")
def main():
print("I'm: " + __name__ + " executing main()")
print("game over")
print("I'm: " + __name__)
if __name__==game(): # game() is returning the string "2"
print("3")
else:
print("4")

How emulate termial iteraction like putty using pySerial

I tried to use pySerial to build a simple terminal to interact COM1 in my PC,
I create 2 threads , one is for READ , the other is for Write
however,
def write_comport():
global ser,cmd, log_file
print("enter Q to quit")
while True:
cmd = raw_input(">>:")
# print(repr(var))
if cmd=='Q':
ser.close()
sys.exit()
log_file.close()
else:
ser.write(cmd + '\r\n')
write_to_file("[Input]"+cmd, log_file)
time.sleep(1)
pass
def read_comport():
global ser, cmd, log_file
while True:
element = ser.readline().strip('\n')
if "~ #" in str(element):
continue
if cmd == str(element).strip():
continue
if "img" in str(element):
print("got:"+element)
beep()
print element
write_to_file(cmd, log_file)
pass
def write_to_file(str,f):
f.write(str)
f.flush
def main():
try:
global read_thr,write_thr
beep()
port_num='COM4'
baudrate=115200
init_serial_port(port_num,baudrate)
read_thr =Thread(target=read_comport)
read_thr.start()
write_thr =Thread(target=write_comport)
write_thr.start()
while True:
pass
except Exception as e:
print(e)
exit_prog()
but the behavior of my code is not as smart as putty or anyother.
cause my function can Not detect whenever the reader is done.
is there any better way to achieve this goal?
By the way, I tried to save the log into txt file real-time . But when I open the file during the process is running, it seems nothing write to my text log file?

Resources