writing live mouse position and RGB using python - python

I'm trying to make a hotkey that when i click in some other program (while script running) a hotkey "1" for example or any other key i assign that it write down the mouse positions and RGB in a text file a single time without spamming it and here is the closest code i could found that at least print the result of mouse position but it doesn't get the colors "RGB"
import pyautogui
import time
import keyboard
c = open("log.txt", "w")
def a():
while True:
if keyboard.read_key() == "1":
x, y = pyautogui.position()
positionStr = str(x).rjust(4) + str(y).rjust(4)
print(positionStr)
c.write(positionStr + '\n')
c.flush()
time.sleep(0.1)
else:
a()
a()
how ever i did find out that one codepyautogui.displayMousePosition() that do show xy and also RGB but im a beginner script kid that have no idea how to save the results to any .txt file
side note: the shown code is copied from some other answer here "https://stackoverflow.com/questions/64046117/write-mouse-position-to-txt-file" and just made the hotkey edit part
and i tried to get it done with myself like this:
c = open("log.txt", "w")
def b(): pyautogui.displayMousePosition()
def a():
while True:
if keyboard.read_key()== '1':
print(b())
c.write(b())
c.flush()
sleep(1)
else:
a()
a()
but it just stuck in the print(b()) command like in a infinite loop showing live xy and RGB but not saving it and when doing ctrl+c it dont save

ok guy i figured it out
c = open("log.txt", "w")
def a():
while True:
if keyboard.is_pressed('1'):
x, y = pyautogui.position()
r,g,b = pyautogui.pixel(x,y)
positionsANDrgb = str(r).rjust(4)+str(g).rjust(4)+str(b).rjust(4)
print(positionsANDrgb)
c.write(positionsANDrgb+'\n')
c.flush()
sleep(1)
a()
i had to add the "sleep(1)" cuz in my single press takes some time like 2third of a second or something like that and command spam as long as i was pressing the hot key
and the '\n' part means new line
u can name the "positionsANDrgb" any thing u want but i just chose this name to make it easier to know what this name for
u dont need the print(positionsANDrgb) part it dont have anything to do with the log.txt but i just added it to see when command is active and "rjust(4)" it adds 4 character of what ever u choose(default is sapce) like "rjust(4,'b')" supposed to give 4 b's sometimes it dont work just increase the 4 till it do in case u wanted it in future
i hope this helped u there who ever needed this like me

Related

How to Print Something Every Other Time Something Happens

I'm trying to learn python and while learning I've come across a bit of a problem.
import time
import pyautogui
def SendScript():
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
I'm trying to print something to the screen every second time the 'enter' key has been pressed, but I'm an extreme beginner so I really don't know how to do that. Could someone help me accomplish this task?
You could create a new boolean variable to track if the enter key has been pressed before. That way, every time the for loop iterates, the value of pressed switches and only when the value of pressed is True will it print something.
import time
import pyautogui
def SendScript():
pressed = False
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
if pressed:
print("Something")
pressed = not pressed
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
From a more step-back approach, you could do:
events=['event1', 'event2', 'event3', 'event4', 'event5', 'event6', 'event7', 'event8']
counter = 0
for event in events:
counter += 1
if counter % 2 == 0: # ie do stuff when divisible by 2, ie when its even
print('print what you want to be printed every second time')
else:
pass
Of course you are not looping through events like I do in this example. The point is counting the events and only doing stuff when this count is even.
As indicated in another answer already, a simple toggle can be implemented with a bool and then code which toggles it every time something happens:
thing = False
:
if happens(something):
thing = not thing
This is fine for toggling between two states. A more general approach which allows for more states is to use a numeric variable and a modulo operator:
times = 0
maxtimes = 12
:
if happens(something):
times += 1
if times % maxtimes == 1:
print("ding dong")
The modulo could be compared to 0 instead if you want to print on the 12th, 24th etc iterations instead of the first, the 13th, etc, or of course any other offset within the period if that's what you want.
Another useful trick is to flip-flop between zero and some other value.
value = 0
othervalue = 1234
:
if happens(something):
value = othervalue - value
Of course, you can flip-flop between any two values actually; subtract the current value from their sum to get the other one.
Needless to say, just toggling or flip-flopping isn't very useful on its own; you'd probably add some (directly or indirectly) user-visible actions inside the if happens(something): block too.
You could use a generator for this:
def everySecondTime():
while True:
yield "hi"
yield "not hi"
mygen = everySecondTime()
print(next(mygen))
print(next(mygen))
print(next(mygen))
print(next(mygen))
This prints
hi
not hi
hi
not hi
I'm sure it's clear to you how you could adapt this to do some other actions instead.
Whether this approach is better than just using a boolean is highly debatable, but I thought I'd leave it here so you could learn about generators (the yield keyword) if you want to.

Update variables in a loop in one python script with input from another python script

This is just an exercise to see how something like this would be done.
In file "variables.py" I have:
x=5
while True:
x=input('input x: ')
In file "loop.py" I have:
import time
from variables import x
while True:
print(str(x))
time.sleep(2)
My goal is to have both programs running, where variables.py constantly asks for a new x value, and loop.py automatically updates the value of x in its loop. I set x=5 so that there's an initial value before I input anything.
Instead, when I run loop.py, I'm given an input prompt. How can I go about achieving something like this?
I don't know if from variables import x works while you run variables.py. So I would suggest to save x in a file what is used by both scripts (but not at the same time!):
x = 5
while True:
x = input('input x: ')
f = open('x.txt', 'w')
f.write(x)
f.close()
and
import time
while True:
f = open('x.txt', 'r')
print(f.read())
f.close()
time.sleep(2)

How to refresh multiple printed lines inplace using Python?

I would like to understand how to reprint multiple lines in Python 3.5.
This is an example of a script where I would like to refresh the printed statement in place.
import random
import time
a = 0
while True:
statement = """
Line {}
Line {}
Line {}
Value = {}
""".format(random.random(), random.random(), random.random(), a)
print(statement, end='\r')
time.sleep(1)
a += 1
What I am trying to do is have:
Line 1
Line 2
Line 3
Value = 1
Write on top of / update / refresh:
Line 1
Line 2
Line 3
Value = 0
The values of each line will change each time. This is effectively giving me a status update of each Line.
I saw another question from 5 years ago however with the addition of the end argument in Python 3+ print function, I am hoping that there is a much simpler solution.
If you want to clear the screen each time you call print(), so that it appears the print is overwritten each time, you can use clear in unix or cls in windows, for example:
import subprocess
a = 0
while True:
print(a)
a += 1
subprocess.call("clear")
If I've understood correctly you're looking for this type of solution:
import random
import time
import os
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')
a = 0
while True:
clear_screen()
statement = """
Line {}
Line {}
Line {}
Value = {}
""".format(random.random(), random.random(), random.random(), a)
print(statement, end='\r')
time.sleep(1)
a += 1
This solution won't work with some software like IDLE, Sublime Text, Eclipse... The problem with running it within this type of software is that clear/cls uses ANSI escape sequences to clear the screen. These commands write a string such as "\033[[80;j" to the output buffer. The native command prompt is able to interpret this as a command to clear the screen but these pseudo-terminals don't know how to interpret it, so they just end up printing small square as if printing an unknown character.
If you're using this type of software, one hack around could be doing print('\n' * 100), it won't be the optimal solution but it's better than nothing.
You could use curses for this.
#!/usr/bin/python3
import curses
from time import sleep
from random import random
statement = """
Line {}
Line {}
Line {}
Value = {}"""
screen = curses.initscr()
n = 0
while n < 20:
screen.clear()
screen.addstr(0, 0, statement.format(random(), random(), random(), n))
screen.refresh()
n += 1
sleep(0.5)
curses.endwin()

How can I print multiple lines, having subsequent lines replacing each of them independently (Python)

I am running a program that works in parallel, utilizing the Pool object from the multiprocessing module.
What I am trying to do is run a function n number of times in parallel, each having a separate loading %, and I would like it to be updating the percentage for each function without replacing other percentages... example:
f(x):
while x < 0:
print 'For x = {0}, {1}% completed...\r'.format(x, percentage),
And I would run the function multiple times in parallel.
The effect I am trying to achieve is the following, for f(10000000), f(15000000), f(7000000):
For x = 10000000, 43% completed
For x = 15000000, 31% completed
For x = 7000000, 77% completed
And the percentages will be updating in their individual lines without replacing for other values of x, in this function f which will be running three times at the same time.
I tried using the carriage return '\r' but that replaces every line and just creates a mess.
Thanks for taking the time to read this post! I hope you can tell me.
I am using Python 2.7 but if it can only be achieved with Python 3 I am open to suggestions.
Curses
As #Keozon mentioned in the comments, one way to achieve this would be to use the curses library.
There is a good guide for curses on the python website.
ANSI Escape Codes
Alternatively, you might try using ANSI escape codes to move the cursor around.
This is in Python3, but it'll work just fine in any version, you'll just need to change the print statements around (or from __future__ import print_function).
print('Hello')
print('World')
print('\033[F\033[F\033[K', end='') # Up, Up, Clear line
# Cursor is at the 'H' of 'Hello'
print('Hi') # Overwriting 'Hello'
# Cursor is at the 'W' of 'World'
print('\033[E', end='') # Down
# Cursor is on the blank line after 'World'
print('Back to the end')
Output:
Hi
World
Back to the end
Edit:
I've done way too much work for you here, but hey, here's basically a full solution using the ANSI method I mentioned above:
import time
import random
class ProgressBar:
def __init__(self, name):
self._name = name
self._progress = 0
#property
def name(self):
return self._name
def get_progress(self):
"""
Randomly increment the progress bar and ensure it doesn't go
over 100
"""
self._progress += int(random.random()*5)
if self._progress > 100:
self._progress = 100
return self._progress
class MultipleProgressBars:
def __init__(self, progress_bars):
self._progress_bars = progress_bars
self._first_update = True
self._all_finished = False
#property
def all_finished(self):
"""
A boolean indicating if all progress bars are at 100
"""
return self._all_finished
def update(self):
"""
Update each progress bar
"""
# We don't want to move up and clear a line on the first run
# so we have a flag to make sure this only happens on later
# calls
if not self._first_update:
# Move up and clear the line the correct number of times
print('\033[F\033[K'*len(self._progress_bars),end='', sep='')
num_complete = 0 # Number of progress bars complete
for progress_bar in self._progress_bars:
name = progress_bar.name
progress = progress_bar.get_progress()
if progress == 100:
num_complete += 1
# Print out a progress bar (scaled to 40 chars wide)
print(
name.ljust(10),
'[' + ('='*int(progress*0.4)).ljust(40) + ']',
str(progress)+'%')
if num_complete == len(self._progress_bars):
self._all_finished = True
self._first_update = False # Mark the first update done
# Create a list of ProgressBars and give them relevant names
progress_bars = [
ProgressBar('James'),
ProgressBar('Bert'),
ProgressBar('Alfred'),
ProgressBar('Frank')
]
# Create a new instance of our MultipleProgressBars class
mpb = MultipleProgressBars(progress_bars)
# Keep updating them while at least one of them is still active
while not mpb.all_finished:
mpb.update()
time.sleep(0.2)

Changing the output inside a while True loop

I am very new in Python and I decided to make a game.
I want a value to be output like this:
Heat: x #x would always be changing
For that I have the following block of code:
while True:
print("Heat: {}".format(Heat))
but all it does is spam "Heat: xHeat: xHeat: x"
When it should be only one Heat bar
What should I do?
In that code 'Heat' in the loop and it will be printed all the time:
Heat = 0
while True:
Heat +=1
print ('Heat: {heat}'.format(heat=Heat))
In that code 'Heat' out of the loop and it will be printed once:
Heat = 0
print ('Heat:')
while True:
Heat +=1
print ('{heat}'.format(heat=Heat))
if you want more newlines use '\n' char (strictly depends on OS).
You can use carriage return to send the cursor to the start of the line.
import sys
while True:
sys.stdout.write("\rHeat: {}".format(Heat))
sys.stdout.flush()
But this approach doesn't sound like you will be able to extend it into any sort of game.
You should look up the python curses library for complete control over the console output.
Also if the number of digits in your output changes then you might want to right-align the output so that you don't get any left-overs. This code demonstrates what happens if you go from a 2 digit number to a 1 digit number:
import sys
import time
for heat in reversed(range(5, 12)):
time.sleep(0.5)
sys.stdout.write("\rHeat: {:>5}".format(heat))
sys.stdout.flush()

Categories

Resources