I need to test functions that use pyautogui. For example, if pressing keyboard key "a" actually press an "a". How can I reproduce this? There is a way to capture the key that it´s been press?
Ideal if it works in Windows and Linux
The PyAutoGUI unit tests have something like this. See the TypewriteThread code for details. Set up a thread to wait a second and call pyautogui.typewrite(), then call input() to accept text. Make sure your window is in focus and the typewrite() thread ends by pressing Enter (the \n character).
import time
import threading
import pyautogui
class TypewriteThread(threading.Thread):
def __init__(self, msg, interval=0.0):
super(TypewriteThread, self).__init__()
self.msg = msg
self.interval = interval
def run(self):
time.sleep(0.25)
pyautogui.typewrite(self.msg, self.interval)
t = TypewriteThread('Hello world!\n')
t.start()
response = input()
print(response == 'Hello world!')
Related
I want to stop awaiting ainput function at 6th iteration of for loop
import asyncio
from aioconsole import ainput
class Test():
def __init__(self):
self.read = True
async def read_from_concole(self):
while self.read:
command = await ainput('$>')
if command == 'exit':
self.read = False
if command == 'greet':
print('greetings :J')
async def count(self):
console_task = asyncio.create_task(self.read_from_concole())
for c in range(10):
await asyncio.sleep(.5)
print(f'number: {c}')
if c == 5: # 6th iteration
# What shoud I do here?
# Following code doesn't meet my expectations
self.read = False
console_task.cancel()
await console_task
# async def run_both(self):
# await asyncio.gather(
# self.read_from_concole(),
# self.count()
# )
if __name__ == '__main__':
o1 = Test()
loop = asyncio.new_event_loop()
loop.run_until_complete(o1.count())
Of course, this code is simplified, but covers the idea: write a program where one coroutine can cancel another which is awaiting something (in this example ainput.
asyncio.Task.cancel() is not the solution because it won't make coroutine stop awaiting (so I need put arbitrary character into console and press enter, this is not what I want).
I don't even know whether my approach makes sense, I'm a fresh asyncio user, for now, I know only the basics. In my real project, the situation is very similar. I have a GUI application and a console window. By clicking 'X' button I want to close window and terminate ainput (which read commands from the console) to completely finish the program (the console part is working on a different thread, and because of that I can't close my program completely - this thread will run until ainput receive some input from a user).
My current code:
from pynput import keyboard
from pynput.keyboard import Key, Controller
import threading
import datetime, time
import os
import subprocess
keyboard = Controller()
def loading():
os.system("open /System/Applications/TextEdit.app")
time.sleep(1)
while running:
keyboard.press("a")
def on_press(key):
global running # inform function to assign (`=`) to external/global `running` instead of creating local `running`
if key == keyboard.Key.left:
running = True
# create thread with function `loading`
t = threading.Thread(target=loading)
# start thread
t.start()
if key == keyboard.Key.down:
# to stop loop in thread
running = False
if key == keyboard.Key.right:
# stop listener
return False
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
Im trying to loop keyboard presses, but stop when right or down key is pressed, but I'm getting an error of "'Controller' object has no attribute 'Listener'". My code works when I don't include the listener part, so I'm not exactly sure how to combine them together to make a cohesive program.
The problem is that you wrote from pynput import keyboard and then after that, keyboard = Controller(), so the same variable keyboard then refers to your instance of Controller, and not the module pynput.keyboard (which is what actually has the Listener class in it)
You can use a different name for that, while instantiating it and then wherever else you use it, such as inside loading(), then the code will work.
Note: Using a loop with no delay like while True: keyboard.press('a') is an absolutely dangerous idea - I've had my computer completely hang, with no response , because of statements like that - and had to shut it down by force to be able to continue doing anything. It's better to include a time.sleep there too.
When I try to make a process start, no matter what, it just fails to do so. This simple code doesn't work:
import multiprocessing
def function():
print("function started")
function_process = multiprocessing.Process(target = function)
function_process.start()
function_process.join()
The output of this code is simply nothing. If I print function_process after this, it returns <Process name='Process-1' pid=13432 parent=7564 stopped exitcode=0>. Adding if __name__ == "__main__" does nothing. Is there something I'm missing here?
Works for me:
$ python mp.py
function started
Maybe the code you show is part of a larger program, and this code is never called?
This is the code:
import multiprocessing
def function():
print("function started")
function_process = multiprocessing.Process(target = function)
function_process.start()
function_process.join()
Some IDEs redirect STDIN, STDERR and STDOUT, and data gets lost. The problem does not happen with Visual Studio Code or PyCharm.
This might be a silly question but:
When you append a given string to a QTextBrowser object, can you make it a link to a signal to a function that takes its text and does something with it? All I need is for it to save the text to a variable actually.
As in, can a link lead to a function instead of to a website.
It certainly is possible.
Here is a code example:
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
main_layout = QtGui.QVBoxLayout()
self.browser = QtGui.QTextBrowser()
self.browser.setHtml('''<html><body>some text<br/>click me to call a function<br/>
Click me to scroll down<br>foo<br>foo<br>foo<br>foo<br>foo<br>foo<br>
foo<a id="my_anchor"></a><br>bar<br>bar<br>bar<br>bar<br>bar<br>bar<br>hello!<br>hello!<br>hello!<br>hello!<br>hello!<br>hello!<br>hello!<br>hello!</body></html''')
self.browser.anchorClicked.connect(self.on_anchor_clicked)
main_layout.addWidget(self.browser)
self.setLayout(main_layout)
def on_anchor_clicked(self,url):
text = str(url.toString())
if text.startswith('some_special_identifier://'):
self.browser.setSource(QtCore.QUrl()) #stops the page from changing
function = text.replace('some_special_identifier://','')
if hasattr(self,function):
getattr(self,function)()
def a_function(self):
print 'you called?'
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Any link that has a url that begins with "some_special_identifier://" will be picked up and the text after that will be used to look up and call a function of the same name. Please note that this could be a little risky as there is the potential for all sorts of functions to be called that perhaps you don't intend, if the user has any control over what is displayed in the TextBrowser. It might be better to only allow certain functions to be run, and perhaps only at certain times. That is of course up to you to enforce!
P.S. my code is written for Python 2.7 (I see you are using Python 3). So I think you will need to change print 'text' to print('text') at the very least!
That's my code:
import threading
import queue
qq=queue.Queue(10)
def x11grab(n):
print('haha')
while True:
a='abcd'+str(n)
n+=1
qq.put(a)
print('put queue:',a)
def rtpsend():
while True:
s=qq.get()
head=s[:4]
body=s[4:]
print('head',head)
print('body',body)
t1=threading.Thread(target=x11grab,args=(1,))
t2=threading.Thread(target=rtpsend)
t1.start
t2.start
I wanna x11grab() function put string 'abcd1','abcd2'... into queue,and rtpsend() function get the string from queue, and display it. It's a demo, but it didn't work. I think your advice could be helpful.:-)
You never start your threads! change
t1.start
t2.start
to
t1.start()
t2.start()