python console terminal sholuld stay on top of any window

692 Views Asked by At

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.

1

There are 1 best solutions below

9
On

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