I want to write the output in a separate notepad or ms word using python package keyboard.
import keyboard
keyboard.write('The quick brown fox jumps over the lazy dog.')
but it writes these sentence in the command prompt, where I run the script, not in notepad.
How can I make it to control the other software?
You need to give your other application focus.
When searching for a method I found this blog post which shows how it can done in Windows:
https://www.blog.pythonlibrary.org/2014/10/20/pywin32-how-to-bring-a-window-to-front/
import win32gui
def windowEnumerationHandler(hwnd, top_windows):
top_windows.append((hwnd, win32gui.GetWindowText(hwnd)))
if __name__ == "__main__":
results = []
top_windows = []
win32gui.EnumWindows(windowEnumerationHandler, top_windows)
for i in top_windows:
if "notepad" in i[1].lower():
print i
win32gui.ShowWindow(i[0],5)
win32gui.SetForegroundWindow(i[0])
break
After the application has focus, you can use your simulated key presses.
You can use pywinauto package which is more efficient and friendly:
from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')
# describe the window inside Notepad.exe process
window = app.UntitledNotepad # or app['Untitled - Notepad'], its the same
# wait till the window is really open
window_ready = window.wait('visible')
# Write in some text
app.UntitledNotepad.Edit.type_keys("Hello world", with_spaces = True)
NOTE: Some lines are adapted from the documentation
Related
Would like your opinion and support on an issue i am trying to overcome. This will be the last piece of puzzle for completion of a small project i am building. Its based on OCR. I am reading text from a live screen ( using below python script ) and able to get the results logged into a file. However, the output is only getting logged once i make the python console window ( in which the script prints the output ) is active/focused by keyboad using alt+tab.
But doing this halts the software from where i am reading the text, breaking the whole process. Toggling the window to the front of the software is a failure to the scripts purpose.
So, i added code after searching from other users about keeping the python console window on top always no matter what the software is doing. I am not able to keep this python console window on top of this sw screen. The SW uses all screen for its purpose of work.
Is there an alternative to this? How can i make the python console become on top of any other window no matter what is on the screen? If not this, please suggest an alternative.
import numpy as nm
from datetime import datetime
import pytesseract
import cv2
import PIL
from PIL import ImageGrab
import win32gui, win32process, win32con
import os
hwnd = win32gui.GetForegroundWindow()
win32gui.SetWindowPos(hwnd,win32con.HWND_TOPMOST,0,0,100,300,0)
#Define function for OCR to enable on multiple screens.
def imToString():
# Path of tesseract executable
pytesseract.pytesseract.tesseract_cmd ='C:\\Tesseract-OCR\\tesseract.exe'
while(True):
# ImageGrab-To capture the screen image in a loop.
# Bbox used to capture a specific area.
#screen base
cap1 = PIL.ImageGrab.grab(bbox =(0, 917, 1913, 1065), include_layered_windows=False, all_screens=True)
date = datetime.now().strftime("%Y-%m-%d %I:%M:%S")
#str config - OCR Engine settings for ONLY text based capture.
config1 = ('-l eng --oem 2 --psm 6')
#configuring tesseract engine for OCR
tess1 = pytesseract.image_to_string(
cv2.cvtColor(nm.array(cap1), cv2.COLOR_BGR2GRAY),
config=config1)
#Defining log pattern to generate
a = [ date, " State: ", tess1 ]
#writing logging output to file
file1 = open("C:\\Users\\User\\Desktop\\rev2.log", "a", encoding='UTF8')
file1.writelines(a)
file1.writelines("\n")
file1.close()
#OUTPUT on colse for Logging verification
print (date, "State: ", tess1)
# Calling the function
imToString()
By requirement, i am not allowed to use a keyboad while operating the screen. I am fairly new to python and have been seeing similar solutions and adding it to the script to make a proper solution.
Please advise.
Here is the tkinter method:
from tkinter import Tk, Text
import subprocess
import threading
from queue import Queue, Empty
filename = 'test.py'
def stream_from(queue):
command = f'python {filename}'
with subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as process:
for out in process.stdout:
queue.put(out.decode())
def update_text(queue):
try:
data = queue.get(block=False)
except Empty:
pass
else:
text.config(state='normal')
text.insert('end', data.strip() + '\n')
text.config(state='disabled')
finally:
root.after(100, update_text, queue)
def loop():
root.attributes('-topmost', True)
root.after(1, loop)
root = Tk()
text = Text(root, state='disabled')
text.pack()
data_queue = Queue()
threading.Thread(target=stream_from, args=(data_queue, ), daemon=True).start()
update_text(data_queue)
loop()
root.mainloop()
Just change the filename to the name of the file you are running and place this script in the same directory
Change delay_in_ms (delay in milliseconds so each 1000 units is one second) and see if that helps (could also leave the 10 seconds and see if it works now, if not there is still another thing to try)
If you are using print to output then this should work (tho I maybe didn't exactly get what you want), if you use logging then there is a slightly different solution
My project is to make a program that you can run while you are playing games or other programs in the background.
When you press a certain key, your notepad should open and also close after you press the same key again.
I have managed to open notepad with subprocess and that works fine but I have no idea to make it open only when a certain key is pressed.
Thanks for any help!
EDIT:
What I tried already:
import subprocess
import keyboard
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
input()
here it just doesn't detect any keyboard input, the input() at the end makes the program not close instantly
import subprocess
import keyboard
keyboard.add_hotkey('ctrl+k', print,args=("hello", "test"))
input()
Here if I press "ctrl+k it" will print hello test that means the hotkey works fine. When I switch this part "print,args=("hello", "test")" to "subprocess.Popen('C:\Windows\System32\notepad.exe')"(it should open the program instead of printing hello test) the notepad opens instantly after I run the program and when I press "ctrl+k" I get a big error.
A more complex, but still working example could be the following. With this code your program will be always listening the keyboard, not only when you are focused on the input, so may be mre practical in your case
from pynput import keyboard
import subprocess
import threading
class MyException(Exception): pass
class Listening:
"""Is allways waiting for the keyboard input"""
def __init__(self):
self.notepad_open = False # to know the state
with keyboard.Listener(
on_press=self.on_press) as listener:
try:
listener.join()
except:
pass
def on_press(self, key):
try:
if key.char == "k":
if not self.notepad_open:
self.subprocess = \
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
self.notepad_open = True # update state
else:
self.subprocess.kill()
self.notepad_open = False # update state
except: # special key was pressed
pass
thread = threading.Thread(target=lambda: Listening())
thread.start()
The problem is that you check for the key 'k' only once at the beginning. If you want the program to correctly work then you should try this:
import time
import subprocess
import keyboard
while True:
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
time.sleep(5)
-I used the time so that you can only open the program once 5 seconds(If you're curious, see what happens without it)-
The context
I am creating my own version of the board game Battleship using PyQt. A PyQt main window contains both own and enemy boards. Boards are made up of clickable tiles that players 'fire at'. The implementation supports HUMANvsAI and AIvsAI games. I would like to test the strength of my AI algorithms through simulation. For example, I would like to run in a loop 1,000 AIvsAI games and get stats on % victory, average accuracy, etc.
The main issue
I am struggling to run the PyQt app multiple times to gather game data, e.g. in a for loop. Specifically, I cannot find a way to run the application, exit it, and re-run it again. Conceptually speaking I am looking for something like this:
# conceptual snippet
for i in range(n):
app = QApplication([])
window = MainWindow(b_size, boat_dict, players)
app.exec_()
With the call to exit the app somewhere else and called each time the game is over:
# conceptual snippet
if is_game_over():
sys.exit(app.exec_())
But this simple solution breaks the for loop. Any feedback would be welcome on how to run and exit a PyQt application multiple times, either sequentially (e.g. for loop approach) or in parallel threads.
You should not use sys.exit() since that instruction serves to terminate the execution of the program, if you want to terminate the Qt application you must use QCoreApplication::quit() (or QCoreApplication::exit(0)). In addition, another improvement would be to use multiprocessing:
import random
from multiprocessing import Pool
from PyQt5 import QtCore, QtWidgets
def create_app(i):
app = QtWidgets.QApplication([])
w = QtWidgets.QMainWindow()
w.setWindowTitle("Game-{}".format(i))
w.show()
# emulate end-game
def end_game():
QtCore.QCoreApplication.quit()
timeout = random.randint(1000, 2000) # 1000-2000 milliseconds
QtCore.QTimer.singleShot(timeout, end_game)
app.exec_()
# emulate results
o = {"victory": random.randint(0, 101), "average": random.randint(0, 101)}
return o
def main():
results = []
pool = Pool(processes=8)
for i in range(1000):
r = pool.apply_async(create_app, args=(i,))
results.append(r)
pool.close()
pool.join()
print([result.get() for result in results])
if __name__ == "__main__":
main()
I've to tell you, your question is dangerously near the level of a "too-broad" flag. The real problem is: how do you want to keep track of the gathered data, and what do you want to do with that data? This question may have a lot of answers.
As you already found out, you can't use sys.exit, but you could gather your data in different ways.
If you're going to run your application within a controlled environment, a possible solution is to serialize your gathered data while controlling the whole "gathering" process from the application
Semi-pseudo-code:
from PyQt5 import QtCore, QtWidgets
import json
class BattleShipWindow(QtWidgets.QMainWindow):
restart = QtCore.pyqtSignal()
# ...
def storeData(self, data):
# get the app data location
appDir = QtWidgets.QStandardPath.standardLocations(
QtCore.QStandardaPaths.AppDataLocation)[0]
# if it doesn't exists, create it
if not QtCore.QFile.exists(appDir):
QtCore.QDir().mkpath(appDir)
now = QtCore.QDateTime.currentDateTime()
fileName = str(now.toMSecsSinceEpoch() // 1000)
# write down the data
with open(os.path.join(appDir, fileName), 'w') as df:
df.write(json.dumps(data))
def getGameData(self):
# gather your own data here, this is just an example
return {'gameData': [1, 2, 3]}
def closeEvent(self, event):
if QtWidgets.QMessageBox.question(
self, 'Play again?',
'Play another game?',
QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No
) == QtWidgets.QMessageBox.Yes:
self.storeData(self.getGameData())
self.restart.emit()
class BattleShipApp(QtWidgets.QApplication):
def restart(self):
self.currentGame = BattleShipWindow()
self.currentGame.restart.connect(self.restart)
self.currentGame.show()
def exec_(self):
self.currentGame = BattleShipWindow()
self.currentGame.restart.connect(self.restart)
self.currentGame.show()
super(BattleShipApp, self).exec_()
if __name__ == '__main__':
import sys
app = BattleShipApp(sys.argv)
sys.exit(app.exec_())
Note: this is a [semi]pseudo code, I obviously didn't test it. Its purpose is to show how it could behave, so don't expect it to work as it is.
i Have developed python application with tkinter framework which is working well on windows platform but the challenge am having is that i can open this application several times as it is shown in the image attached.
I want the application to open only once. If the app is opened and the user clicks on the icon on the desktop to open it again it shouldn't open because it is already being opened.
I want to achieve this function as it works in apps like Teamviewer , pycharm and etc.
Your suggestions are welcome to achieve this.
EDIT
This the how am trying to terminate the but after adding this to the code the executable doesn't runned again;
import psutil
import tkinter as tk
root = tk.Tk()
root.geometry("400x400")
b = tk.Button(root, text="hello world button", command=None)
b.place(x=200, y=100)
PROCNAME = "myapp.exe"
for proc in psutil.process_iter():
# check whether the process name matches
if proc.name() == PROCNAME:
print("Running, exit(1).")
exit(1)
else:
print("not running, continue to startup.")
root.mainloop()
root.mainloop()
Question: How to open python software only once
My Comment,
Find running processes using psutil and terminate.
should be written
Find running processes using psutil and exit.
if __name__ == "__main__":
PROCNAME = "myapp.exe"
for proc in psutil.process_iter():
# check whether the process name matches
if proc.name() == PROCNAME:
print("Running, exit(1).")
exit(1)
print("not running, continue to startup.")
App().mainloop()
I whipped up a basic voice assistant using what I know on python with some research, as a self learning project.
Link to the code is here
I am basically converting the audio to text and then splitting it to look for keywords and then trigger a response or an action so to speak, which is not very intelligent but it's working for the time being.
How else can I look for keywords, is there a better approach, an efficient way, if you will, than a thousand lines of ifs and elifs?
Another problem I have is, I built a GUI interface for this program so I could interact with it at the click of a button but the problem is, the window isn't responding after clicking the button, turns out it's a known problem and I don't know how to get around it as I don't know the concept of threads and processes and queues. I am hoping that someone could help me with my problem.
I would like to point out that if I have to do any learning for this project, I would be interested to do that since the idea behind this whole project is learning how to code or build an AI, which may sound stupid
PS: I implemented, well, sort of did, always listen feature or keep running feature by keeping the function in a while loop. I would like to find a way for a voice speech trigger as well to wake up the assistant. Any help in that aspect would be much appreciated.
And also, help me set a name to this assistant, preferably female.
The code is here:
import os
import time
import random
import webbrowser
import tkinter as tk
from gtts import gTTS
from mutagen.mp3 import MP3
from PIL import ImageTk, Image
from playsound import playsound
import speech_recognition as sr
from weather import Weather, Unit
def startAssistant():
keepRunning = 1
while keepRunning is 1:
mainFunction()
if mainFunction() is 0: break
def doNothing(): print("I don't do anything apart from printing this line of course!")
def mainFunction():
f = open("assistant.txt", "a")
# Printing what a user is saying for better user experience
def say(text):
print(text)
f.write("\n" + text + "\n")
return text
# This function will take inputs to talk back
def talkBack(text, recordingName):
# Variable Declaration
extension = ".mp3"
# Synthesising the reponse as speech
tts = gTTS(text=say(text), lang="en-us")
# Saving the response files
fileName = recordingName + extension
audioPath = "audioFiles\\"
responseFile = audioPath + fileName
# Checking to see if the file is already created
if not os.path.exists(responseFile):
tts.save(responseFile)
# Playing the audio
playsound(responseFile)
# Initialising things here
recognizer = sr.Recognizer()
microphone = sr.Microphone()
# Asking for input and saving that
with microphone as source:
print ("Speak:")
audio = recognizer.listen(source)
# Converting audio into text
convertedAudio = recognizer.recognize_google(audio)
convertedAudioSplit = convertedAudio.split()
# Printing what was picked up when the user Spoke and also logging it
print("\n" + convertedAudio + "\n")
f.write("\n" + convertedAudio + "\n")
# Start of a conversation
if "hello" in convertedAudioSplit:
talkBack("Hi, how are you doing today?", "hello")
# Wishing people based on the time of the day
elif "morning" in convertedAudioSplit:
talkBack("Good morning! The sun's shining bright, let's head out for a run. We'll get back and make a healthy breakfast for ourselves", "morning")
elif "afternoon" in convertedAudioSplit:
talkBack("Good afternoon! You must be hungry right about now, why don't you break for lunch?", "afternoon")
elif "night" in convertedAudioSplit:
talkBack("Nighty night sleepy pot! Get a good night's sleep while I learn more to be more helpful to you tomorrow.", "night")
# Getting her information
elif "doing" in convertedAudioSplit:
talkBack("I am doing very good, Thank you for asking!", "doing")
# Making the assistant open web browser with a URL
elif "Google" in convertedAudioSplit:
talkBack("Okay, lets get you to Google.", "google")
# Opening the browser with the required URL
webbrowser.open("https://www.google.com/", new = 1)
# Brings the weather report
elif "weather" in convertedAudioSplit:
weatherVariable = Weather(unit=Unit.CELSIUS)
location = weatherVariable.lookup_by_location('bangalore')
condition = location.condition.text
talkBack("It is {0} right now in Bengaluru.".format(condition), "weather")
# Exiting the program on user's consent
elif "exit" in convertedAudioSplit:
talkBack("Sure, if that's what you want! I will miss you, have a good day.", "exit")
return 0
# If there is an UnknownValueError, this will kick in
elif sr.UnknownValueError:
talkBack("I am sorry, I couldn't quite get what you said. Could you please say that again?", "UnknownValueError")
# When things go out of the box
else:
# Out of scope reply
talkBack("I am a demo version. When you meet the completed me, you will be surprised.", "somethingElse")
return 0
root = tk.Tk()
root.title("Voice Assistant")
mainFrame = tk.Frame(root, width = 1024, height = 720, bg = "turquoise", borderwidth = 5)
menu = tk.Menu(root)
root.config(menu=menu)
subMenu = tk.Menu(menu)
startButton = tk.Button(mainFrame, text="Interact", command = startAssistant)
startButton.place(relx = 0.5, rely = 1.0, anchor = tk.S)
menu.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Do Nothing", command=doNothing)
subMenu.add_separator()
subMenu.add_command(label="Exit", command=root.quit)
mainFrame.pack()
root.mainloop()
One potential solution is to use a simpler GUI package. Perhaps the GUI package PySimpleGUI would be a fit. It could solve your GUI problem and free you up to work on the other portions of your project.
Check out the Chat Demo that implements a Chat front-end. Therre's also a Chatterbot Demo that implements a front-end to the Chatterbot project.
You can start by copying that code and modifying it.