How to print the progress of a task at somewhere fixed in python3.7 - python-3.x

I'm trying to run a time time-consuming 'for' loop, and want to print the process in the fixed place of the console and refresh each loop
I try print function like this
for i in range(total):
...some code....
print('---%.2f---'%(float(i)/total), sep='')
It seems does't work

I use this answer to display progress bar:
The methods used:
def startProgress(title):
global progress_x
sys.stdout.write(title + ": [" + "-"*50 + "]" + chr(8)*51)
sys.stdout.flush()
progress_x = 0
def progress(x):
global progress_x
x = int(x * 50 // 100)
sys.stdout.write("#" * (x - progress_x))
sys.stdout.flush()
progress_x = x
def endProgress():
sys.stdout.write("#" * (50 - progress_x) + "]\n")
sys.stdout.flush()
An example of use:
import time
import sys
startProgress("Test")
for i in range(500):
progress(i * 100 / 500)
time.sleep(.1)
endProgress()
The progress will look like this with the # moving at the same time of the progress:

Related

Windows 10 Crashes when Running Python Code (PyVisa)

I'm trying to automate data collection from an SR245 Boxcar using Python 3.6 and the PyVisa library (version 1.11.1). 9/10 times, it works great. However, three times over the course of two days it has caused the entire computer to crash and reboot (running on Windows 10). This has resulted in a lot of data loss, and I'm trying to figure out what I'm doing wrong that is leading to the whole system crashing. Code is below (it is part of a larger program, but I also run this piece of code by itself, and it has caused crashes). The data_processing file is not shown, but the functions there are simple calculations (e.g. divide the values in a list by the values in another list, return the average value from a list of integers, etc.)
import pyvisa
from pyvisa.constants import SerialTermination
import time
import numpy as np
from data_processing import *
def connect_boxcar(pNum):
rm = pyvisa.ResourceManager()
port = "COM"+pNum
sr = rm.open_resource(port)
return sr
def config_boxcar(boxcar):
#Configure the boxcar settings
boxcar.write_termination = '\r'
boxcar.read_termination='\r'
boxcar.baud_rate=19200
boxcar.end_output = SerialTermination.termination_char
def preset_scan(boxcar):
#Reset boxcar settings
boxcar.write('MR')
boxcar.write('MS;ET;T1;I2;W0')
def scan(boxcar, num):
#Send the SCAN command to the boxcar, set to the specified number of data points
command = 'SC1,2:' + str(num)
boxcar.write(command)
def read_data(boxcar, num):
#Read the stored scan data and return it as a value list
data_list = []
for x in range(num * 2):
data_list.append(float(boxcar.query('N')))
return data_list
def collect_baseline(boxcar, n):
#Get a baseline signal for later processing
config_boxcar(boxcar)
preset_scan(boxcar)
scan(boxcar, n)
raw_data = read_data(boxcar, n)
chan1 = raw_data[::2]
chan2 = raw_data[1::2]
normal_data = normalize(chan1, chan2, n)
return average_list(normal_data)
def main():
rm = pyvisa.ResourceManager()
n = 10
sleep_timer = 0.1 * n + 0.5
sr245 = rm.open_resource('COM5')
#Configure/preset
config_boxcar(sr245)
preset_scan(sr245)
#Set a timer to measure scanning time
t0 = time.time()
scan(sr245, n)
time.sleep(sleep_timer)
raw_data = read_data(sr245, n)
t1 = time.time()
#Breakdown data by channel and normalize
chan1 = raw_data[::2]
chan2 = raw_data[1::2]
normal_data = normalize(chan1, chan2, n)
elapsed_time = t1 - t0
print('Elapsed time: ', elapsed_time)
print('Channel 1: ', chan1)
print('Channel 2: ', chan2)
print('Normalized Data: ', normal_data)
print('Average Normalized Data: ', average_list(normal_data))
print('Standard Deviation: ', np.std(normal_data))
if __name__ == '__main__':
main()

Running single python script with different crontab commands

I'm trying to create a single python script that needs to run in a multiple instance continuously parallel to each other on the background.
I tried using crontab in ubuntu 20.04 and have the following
* * * * * python3 ~/Documents/xxx/pollingservice.py -d 185 > /tmp/log 2>&1
1 * * * * python3 ~/Documents/xxx/pollingservice.py -d 186 > ~/Documents/logs 2>&1
1 * * * * python3 ~/Documents/xxx/pollingservice.py -d 186 > ~/Documents/logs-186 2>&1
1 * * * * python3 ~/Documents/xxx/pollingservice.py -d 187 > ~/Documents/logs-187 2>&1
Basically I want to run this single script with multiple arguments. what they are doing is fetching data from device using a modbus protocol and save it in a csv file. However it seems like the cronjob is not running there isn't any log file being created after 1 minute of restarting the cron using the command service cron start
the following is the python script
from pymodbus.client.sync import ModbusTcpClient
from ast import literal_eval
import requests
import json
import time
import datetime
import csv
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--device", help="Device ID")
args = parser.parse_args()
def pollData(devices):
items = []
client = ModbusTcpClient(host=devices['ip_address'], port=devices['port'])
connection = client.connect()
alarm = "NO ALARM"
for driver in devices['thresholds']['threshold_data']:
try:
address = literal_eval('0x0{}'.format(driver['hex_offset'].rstrip('H')) or 0)
response = client.read_holding_registers(address, 10, unit=int(devices['slave_id']))
converted = response.registers[0] / int(driver['register_scale'])
bin8 = lambda x: ''.join(reversed([str((x >> i) & 1) for i in range(16)]))
try:
value = float(round(converted, 2))
print(value)
if float(converted) < float(driver['low_critical'] or 0):
alarm = "LOW CRITICAL"
print('LOW CRITICAL')
elif float(driver['low_warning'] or 0) > float(converted) > float(driver['low_critical'] or 0):
alarm = "LOW WARNING"
print('LOW WARNING')
elif value > float(driver['high_warning'] or 0):
alarm = "HIGH WARNING"
print('High Warning')
elif value > float(driver['high_critical'] or 0):
alarm = "HIGH CRITICAL"
print('High Critical')
sendData(devices['device_id'], value, alarm)
except TypeError as e:
print(e)
timestamp = str(datetime.datetime.now())
items.append(round(converted, 2))
average = average_list(items)
maximum_value = max(items)
minimum_value = min(items)
# Send data to threshold and save only every 15 minutes
send_poll(devices['device_id'], round(converted, 2), driver['address'], minimum_value, maximum_value, average)
with open('/home/xxx/Documents/csv' + csv_name, 'a+', newline='') as f:
driver_writer = csv.writer(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
driver_writer.writerow([timestamp,
devices['device_id'],
devices['slave_id'],
driver['address'],
round(converted, 2),
alarm])
except ValueError as e:
print(e)
continue
return items
def sendData(device_id, alarm_value, alarm_status):
r = requests.post('http://xxx/store-alarm', data={
'device_id': device_id,
'alarm_value': alarm_value,
'alarm_status': alarm_status
})
def send_poll(device_id, value, modbus_address, min_value, max_value, average_value):
r = requests.post('http:/xxx', data={
'device_id': device_id,
'modbus_address': modbus_address,
'value': value,
'min_value': min_value,
'max_value': max_value,
'average_value': average_value,
})
print(r)
def average_list(lst):
return sum(lst) / len(lst)
while True:
try:
devices = requests.get('http://xxxx'.format(str(args.device))).json()
data = pollData(devices)
time.sleep(3)
except Exception as e:
print(e)
continue
is there anything i can do here to make them run parallel to each other? Thanks!

How can I use input function to fill the parameters?

Create a function called computepay which takes two parameters (hours and rate ).
Enter Hours: 45
Enter Rate: 10
Pay: 475.0
This is my code, but it doesn't show an input dialog when I run the program.
def computepay(x, y):
x = input('Enter Hours: ')
y = input('Enter Rate: ')
if int(x) <= 40 :
print('\nPay: ' + int(x) * int(y))
else :
print('\nPay: ' + 40 * int(y) + ((int(x) - 40) * 15))
If you want to just call the function with zero or empty string or even you can pre define in it, now you can get the input dialog in whatever ide you are using
def computepay(x=0, y=0):
x = input('Enter Hours: ')
y = input('Enter Rate: ')
if int(x) <= 40 :
print('\nPay: ' + str(int(x) * int(y)))
else :
print('\nPay: ' +str( 40 * int(y) + ((int(x) - 40) * 15)))
computepay()
Do like this and let me know if that works out for you Dale
def computepay():
x = int(input('Enter Hours: ')) #this is the way to get int input
y = int(input('Enter Rate: '))
if x <= 40 :
basicCompute = x * y
#use f-string instead, it is clean and correct, the way you were doing things with the print was wrong
print(f'\nPay: {basicCompute}')
else :
# have a variable which computes that for you, don't do that in your print directly
compute = (40 * y) + ((x - 40) * 15)
print(f'\nPay: {compute}')
# this is how you call your method
computepay()
OUTPUT
# this is how you get the thing in your terminal, tested and verified
Enter Hours: 30
Enter Rate: 10
Pay: 300
ALTERNATIVE
If you want your method to accept the two arguments, then do not do input() inside your method
def computepay(x, y):
# use x and ye with the arguments only
if x <= 40 :
basicCompute = x * y
print(f'\nPay: {basicCompute}')
else :
compute = (40 * y) + ((x - 40) * 15)
print(f'\nPay: {compute}')
# When you call your method, before that you have to accept x and y params, then
# pass it to your method
hours = int(input('Enter Hours: '))
rate = int(input('Enter Rate: '))
# then pass it to your method
# this will do the call, and print the data in your console
computepay(hours, rate)
Hope that helps :)
You need to call that function below.
computepay(parameterA,parameterB)
Mind the indentation issues!

Having an issue getting TKinter to track mouse movement to an object

I was unsure whether to post the full code or not, but here's what I have:
from tkinter import *
from random import randint
HEIGHT = 500
WIDTH = 800
MID_X = WIDTH/2
MID_Y = HEIGHT/2
SHIP_R = 15
SHIP_SPD = 10
bub_id = list()
bub_r = list()
bub_speed = list()
MIN_BUB_R = 10
MAX_BUB_R = 30
MAX_BUB_SPD = 6
GAP = 100
window = Tk()
window.title('Bubble Blaster')
c = Canvas(window, width=WIDTH, height=HEIGHT, bg='darkblue')
c.pack()
ship_id = c.create_polygon(5, 5, 5, 25, 30, 15, fill='red')
ship_id2 = c.create_oval(0, 0, 30, 30, outline='red')
c.move(ship_id, MID_X, MID_Y)
c.move(ship_id2, MID_X, MID_Y)
def move_ship(event):
fixed = True
while fixed == True:
ship_x, ship_y = event.x, event.y
c.move(ship_id, ship_x, ship_y)
c.move(ship_id2, ship_x, ship_y)
sleep(0.01)
def create_bubble():
x = WIDTH + GAP
y = randint(0, HEIGHT)
r = randint(MIN_BUB_R, MAX_BUB_R)
id1 = c.create_oval(x-r, y-r, x+r, y+r, outline='white')
bub_id.append(id1)
bub_r.append(r)
bub_speed.append(randint(1, MAX_BUB_SPD))
def move_bubbles():
for i in range(len(bub_id)):
c.move(bub_id[i], -bub_speed[i], 0)
def get_coords(id_num):
pos = c.coords(id_num)
x = (pos[0] + pos[2])/2
y = (pos[1] + pos[3])/2
return x, y
def del_bubble(i):
del bub_r[i]
del bub_speed[i]
c.delete(bub_id[i])
del bub_id[i]
def clean_up_bubs():
for i in range(len(bub_id)-1, -1, -1):
x, y = get_coords(bub_id[i])
if x < -GAP:
del_bubble(i)
from math import sqrt
def distance(id1, id2):
x1, y1 = get_coords(id1)
x2, y2 = get_coords(id2)
return sqrt((x2-x1)**2 + (y2-y1)**2)
def collision():
points = 0
for bub in range(len(bub_id)-1, -1, -1):
if distance(ship_id2, bub_id[bub]) < (SHIP_R+bub_r[bub]):
points += (bub_r[bub] + bub_speed[bub])
del_bubble(bub)
return points
c.create_text(50, 30, text='TIME', fill='white')
c.create_text(150, 30, text='SCORE', fill='white')
time_text = c.create_text(50, 50, fill='white')
score_text = c.create_text (150, 50, fill='white')
def show_score(score):
c.itemconfig(score_text, text=str(score))
def show_time(time_left):
c.itemconfig(time_text, text=str(time_left))
from time import sleep, time
BUB_CHANCE = 20
TIME_LIMIT = 30
BONUS_SCORE = 1000
# MAIN GAME LOOP
c.bind("<B1_Motion>", move_ship)
score = 0
bonus = 0
end = time() + TIME_LIMIT
while time() < end:
if randint(1, BUB_CHANCE) == 1:
create_bubble()
move_bubbles()
move_ship("<B1_Motion>")
clean_up_bubs()
score += collision()
if (int(score / BONUS_SCORE)) > bonus:
bonus += 1
end += TIME_LIMIT
show_score(score)
show_time(int(end-time()))
window.update()
sleep(0.01)
c.create_text(MID_X, MID_Y, \
text='PARTY TIME, EXCELLENT', fil='white', font=('Helvetica', 30))
c.create_text(MID_X, MID_Y + 30, \
text='Score: ' + str(score), fill='white')
c.create_text(MID_X, MID_Y + 45, \
text='BONU TIME: ' + str(bonus*TIME_LIMIT), fill='white')
I'm a complete beginner when it comes to python, and have been given an assignment to only use tkinter and the standard libraries to give mouse movement to this "game". I just can't seem to get the right grasp of it. Any suggestions would be appreciated!
The first step is to remove your while loop, and put most of your functionality into a function. Put everything you want to do in a single frame of animation into this function.
Next, call this function on a regular interval using the after command. This allows the event loop to run continuously, which is important for your UI to be responsive. You can do your time() < end calculation inside this function, and use the result to break the cycle once time is up.
It looks something like this:
def draw_one_frame():
if randint(1, BUB_CHANCE) == 1:
create_bubble()
move_bubbles()
# move_ship("<B1_Motion>")
clean_up_bubs()
score += collision()
if (int(score / BONUS_SCORE)) > bonus:
bonus += 1
end += TIME_LIMIT
show_score(score)
show_time(int(end-time()))
if time() < end:
after(10, draw_one_frame)
You can use the first parameter to after to control how many frames per second you wish your program to run at.
Next, you need to handle mouse movement. You do this by creating a binding to the movement of the mouse. You do this outside of the draw_one_frame method. It looks something like this:
c.bind("<B1-Motion>", move_ship)
You also need to remove the infinite loop from move_ship, and also remove the sleep. You simply need to do all the calculations for the current mouse position. The function will be already be looping -- being called once each time the mouse moves.
Finally, you need to call window.mainloop() after all your other code, so that the program can process events. This should be the very last line of your program. It will run until the window is destroyed.

VIDLE - Py 2.7 after saving as .py, no longer runs

I have been learning python for physics,
im using VIDLE - Py 2.7,
I open a new file and without saving enter this code:
from visual import *
scene.width = 800
scene.height = 600
scene.autoscale = 0
scene.range = (100, 100, 100)
scene.center = (0, 40, 0)
#scene.fullscreen = 1
ball = sphere(pos=(0,103,1),radius = 2)
ground = box(pos=(0,-1,0),size=(100,2,100))
building = box(size = (6,100,6),pos=(0,50,0),color=color.blue)
gravity = 9.8 # m/s**2
velocityX = 7 #m/s
seconds = 0
dt = 0.05
finished = False
while not finished:
rate(100) # dont run through loop more than 100 times/sec
seconds += dt
#position equation; y(t) = y0 + v0*t + .5 * a * t**2
ballY = 100 - .5 * gravity * seconds**2
ballX = velocityX * seconds
ball.pos = vector(ballX, ballY, 0)
if ballY -2 <=0:
finished = True
print "seconds to drop: " + str(seconds)
this successfully runs the program, but when i save it as a .py and then try to run it again in the same way I get an error
Traceback (most recent call last):
File "/Users/bencallaghan/Desktop/psyre.py", line 1
from visual import *
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/VPython-6.05-py2.7-macosx-10.6-intel.egg/visual/init.py", line 34
from visual_common.create_display import *
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/VPython-6.05-py2.7-macosx-10.6-intel.egg/visual_common/create_display.py", line 10
import wx as _wx
File "/usr/local/lib/wxPython-2.9.4.0/lib/python2.7/site-packages/wx-2.9.4-osx_cocoa/wx/init.py", line 45
from wx._core import *
File "/usr/local/lib/wxPython-2.9.4.0/lib/python2.7/site-packages/wx-2.9.4-osx_cocoa/wx/_core.py", line 5
import new
File "/Users/bencallaghan/Desktop/new.py", line 8
from pylab import scatter,xlabel,ylabel,xlim,ylim,show
ImportError: No module named pylab
My guess is that its running in some type of shell within Vpython that has access to visual and pylab but when I save it then tries to access them from somewhere else and it can't.
But beyond that reasoning I have little idea where to go from there
any ideas?
For starters, you need to import pylab in the same way that you imported vpython at the first line.
from pylab import*
Also, it seems you will need to indent this way so that your position/velocity updates are contained within your while loop. Hope this helps
while not finished:
rate(100) # dont run through loop more than 100 times/sec
seconds += dt
#position equation; y(t) = y0 + v0*t + .5 * a * t**2
ballY = 100 - .5 * gravity * seconds**2
ballX = velocityX * seconds
ball.pos = vector(ballX, ballY, 0)
if ballY -2 <=0:
finished = True
print "seconds to drop: " + str(seconds)
PS Not sure if the space between "import" and "*" is causing problems on your first line as well, should be:
from visual import*
not:
from visual import *
but this may be ok

Resources