Python script keeps running in the background - python

This is a simple script that is used to calculate Z scores of some neuropsychological tests.
But recently the code seems to be running on the background even after exiting the program. This problem didn't exist before, I use the following startup piece to ensure program is running with elevation, and is correct size for the display.
Program can be shut down using a "exit" command that raises SystemExit or just by pressing the X button on the top bar. Program keep running on the background regardless.
Where did I go wrong?
def progStructure():
first_run = True
if first_run:
import os
os.system("mode con: cols=160 lines=50")
print("""
================================================
PROGRAM GREETING
================================================
""")
mainStartup()
first_run = False
while settings("auto_run"):
mainStartup()
#this function contains the main program, but irrelevant to the question
print("Auto shutdown enabled, program is shutting down.")
wait(2)
exit()
#informs the user data has been saved then restarts
import ctypes, sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
progStructure()
else:
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, "", None, 0)
progStructure()
My excel writing function:
def excelWriter(excel_path, data_num, printable_list):
from time import strftime
date = strftime("%Y-%m-%d")
time = strftime("%H:%M:%S")
if settings("excel_output_subjectNames"):
patient_name_local = patient_name
else:
patient_name_local = "N/A"
demographic_data = [patient_ID, patient_name_local, patient_admin, date, time, patient_age, patient_sex, patient_edu]
from openpyxl import Workbook
from openpyxl import load_workbook
wb = Workbook(write_only=False)
try:
test_name_list = [
"(1)MMT", "(2)MOCA", "(3)3MS", "(4)GISD", "(5)ECR",
"(6)Sözel Bellek Süreçleri", "(7)Rey Karmaşık Figür", "(8)İz Sürme", "(9)Stroop",
"(10)Wisconsin", "(11)Görsel Sözel Test", "(12)Renkli İz Sürme",
"(13)Wechsler", "(14)Wechsler-Sayı Dizisi", "(15)Sözel Akıcılık",
"(16)Semantik Akıcılık", "(17)Saat Çizme", "(18)SDOT", "(19)Ayları İleri-Geri Sayma"
]
while True:
try:
data_workbook = load_workbook(filename = excel_path + settings("excel_name"), read_only=False)
active_sheet = data_workbook.get_sheet_by_name(test_name_list[data_num-1])
active_sheet.append(demographic_data + printable_list)
data_workbook.save(filename = excel_path + settings("excel_name"))
break
except:
for i in range(len(test_name_list)):
wb.create_sheet(title = test_name_list[i])
wb.save(filename = excel_path + settings("excel_name"))
data_workbook = load_workbook(filename = excel_path + settings("excel_name"), read_only=False)
active_sheet = data_workbook.get_sheet_by_name("Sheet")
data_workbook.remove_sheet(active_sheet)
data_workbook.save(filename = excel_path + settings("excel_name"))
continue
except:
raise

Forgot to close the excel file after writing, that seemingly fixed the problem, thanks for everyone helping out.

Related

Is it possible to pass a xlwings object to multiprocessing?

My goal is to write a program in python that opens an Excel workbook and starts a macro. If the macro is not completed within a certain amount of time or if it encounters an error, the program should exit. This should not only terminate the process, but also close the Excel workbook. Unfortunately, it is not possible to pass the created Excel workbook to the multiprocessing process.
import pythoncom
import xlwings as xw
import multiprocessing as mp
import time
def ExcelFunktionStarten(pfad, startanweisung, maxWartezeit):
pythoncom.CoInitialize()
xl_app = xw.App(visible=True, add_book=False)
t1 = mp.Process(target=ExcelRun, args=(pfad, startanweisung, xl_app, ))
t1.start()
vergangeneZeit = 0
while t1.is_alive():
if vergangeneZeit > maxWartezeit:
t1.terminate()
time.sleep(1)
xl_app.quit()
break
else:
print(vergangeneZeit, t1.is_alive())
print(xl_app)
vergangeneZeit += 1
time.sleep(1)
def ExcelRun(pfad, startanweisung, xl_app):
try:
wb = xl_app.books.open(pfad)
run_macro = wb.app.macro(startanweisung)
run_macro()
wb.save()
wb.close()
xl_app.quit()
except:
xl_app.quit()

Printing files within a folder using python

I am trying to improve a code I found online so that it doesn't waste so much paper.
The files I will be printing are small labels which do not take a lot of space. I would like to be able to "merge" those labels so that they'd be printed out by groups of 6 per page.
This is the code (it already has some modifications):
# Import libraries
import os
from pickle import TRUE
import time
import tkinter as tk
from tkinter import filedialog
def menu():
print("1- Retry")
print("0- Exit")
s=TRUE
while s:
opt = input("Select an option: ")
try:
if int(opt) == 1 or int(opt) == 0:
opt = int(opt)
s = False
except:
input("Press enter to try again.")
return opt
s = TRUE
while s:
root = tk.Tk()
root.withdraw()
path = filedialog.askdirectory()
try:
# Extracting all the contents in the directory corresponding to path
l_files = os.listdir(path)
# Iterating over all the files
for file in l_files:
# Instantiating the path of the file
file_path = f'{path}\\{file}'
# Checking whether the given file is a directory or not
if os.path.isfile(file_path):
try:
# Printing the file pertaining to file_path
os.startfile(file_path, 'print')
print(f'Printing {file}')
# Sleeping the program for 5 seconds so as to account the
# steady processing of the print operation.
time.sleep(5)
except:
# Catching if any error occurs and alerting the user
print(f'ALERT: {file} could not be printed! Please check\
the associated softwares, or the file type.')
else:
print(f'ALERT: {file} is not a file, so can not be printed!')
s = False
except:
print('No folder selected.')
opt = menu()
if opt == 0:
break
else:
pass
print('Task finished!')

Python code doesn't call class from another program when Import statement is used

I'm trying to write a code a that gets user input via pop up and use that in different program.
below is the code which gets user input.
Excel_connection.py
import openpyxl
import tkinter as tk
class App(tk.Frame):
def __init__(self,master=None,**kw):
#Create a blank dictionary
self.answers = {}
tk.Frame.__init__(self,master=master,**kw)
tk.Label(self,text="Give Input Sheet Path").grid(row=0,column=0)
self.Input_From_User1 = tk.Entry(self)
self.Input_From_User1.grid(row=0,column=1)
tk.Button(self,text="Feed into Program",command =
self.collectAnswers).grid(row=2,column=1)
def collectAnswers(self):
self.answers['Input_Path'] = self.Input_From_User1.get()
global Input_Path
Input_Path = self.answers['Input_Path']
functionThatUsesAnswers(self.answers)
quit()
def quit():
root.destroy()
if __name__ == '__main__':
root = tk.Tk()
App(root).grid()
root.mainloop()
wb = openpyxl.load_workbook(Input_Path) # trying to open the open the input sheet from the
below path
ws = wb["Sheet1"]
Below is the code where i'm importing the above program which does some operation
Execution.py
import pandas
from Excel_Connection import *
from Snowflake_Connection import *
all_rows = list(ws.rows)
cur = ctx.cursor()
# Pull information from specific cells.
for row in all_rows[1:400]:
scenario = row[1].value
query = row[2].value
if_execute = row[3].value
if if_execute == 'Y':
try:
cur.execute(query)
df = cur.fetch_pandas_all()
except:
print(scenario," Failed")
else:
print("CREATED",scenario,".csv successfully")
print("ALL INDIVDUAL REPORT GENERATED")
When I'm executing Execution.py, the program does not produce pop up window and instead the code throws below error,
wb = openpyxl.load_workbook(Input_Path) # trying to open the open the input sheet from the below path
NameError: name 'Input_Path' is not defined
I tried to -
executing Excel_connection.py separately and it just worked fine.
place the code directly instead of importing the program in the Execution.py and again it worked fine as expected.
The only time I'm facing issue is when I try to import the Excel_connection.py into Excel_connection.py
Could somebody kindly help me out here.
When you import Excel_connection.py, it'll run the code in it.
So as you run Execution.py:
import pandas -> "run" the pandas stuff to define functions, etc...
from Excel_connection import * -> You import everything from Excel_connection. So the interpreter will open this file, parse, and run:
2.1 Class App is defined
2.2 runs: wb = openpyxl.load_workbook(Input_Path), which is a nonsense. Since as I see Input_Path is defined in App.collectAnswers(), which was never executed before. So there is no Input_Path to use... And you program terminates here, and tells you that.
If you run your Excel_connection.py directly, it'll work, because the if __name__ == '__main__' is True in this case and that section runs too. But if you import the file, it is false so you skip that part of the code.
You should move this to the Execution.py file before the all_rows = list(ws.rows) line
wb = openpyxl.load_workbook(Input_Path) # trying to open the open the input sheet from the
below path
ws = wb["Sheet1"]
And it'll still break since we have no Input_Path, so you must define it somehow, but it is up to you how. You can create an App like how you do it in the Excel_connection.py.
But I shouldn't do that since it is a little ugly. I would do something like:
Excel_Connection.py
import openpyxl
import tkinter as tk
class App(tk.Frame):
def __init__(self,master=None,**kw):
#Create a blank dictionary
self.answers = {}
tk.Frame.__init__(self,master=master,**kw)
tk.Label(self,text="Give Input Sheet Path").grid(row=0,column=0)
self.Input_From_User1 = tk.Entry(self)
self.Input_From_User1.grid(row=0,column=1)
tk.Button(self,text="Feed into Program",command =
self.collectAnswers).grid(row=2,column=1)
def collectAnswers(self):
self.answers['Input_Path'] = self.Input_From_User1.get()
global Input_Path
Input_Path = self.answers['Input_Path']
functionThatUsesAnswers(self.answers)
self.quit()
# def quit():
# root.destroy()
def main():
root = tk.Tk()
App(root).grid()
root.mainloop()
wb = openpyxl.load_workbook(Input_Path) # trying to open the open the input sheet from the below path
return wb["Sheet1"]
if __name__ == '__main__':
main()
and then
Execution.py
import pandas
import Excel_Connection
from Snowflake_Connection import *
# Now we call the main() function from Excel_Connection, which will return the worksheet for us.
ws = Excel_Connection.main()
all_rows = list(ws.rows)
cur = ctx.cursor()
# Pull information from specific cells.
for row in all_rows[1:400]:
scenario = row[1].value
query = row[2].value
if_execute = row[3].value
if if_execute == 'Y':
try:
cur.execute(query)
df = cur.fetch_pandas_all()
except:
print(scenario," Failed")
else:
print("CREATED",scenario,".csv successfully")
print("ALL INDIVDUAL REPORT GENERATED")
you can simply use
csv files
or some file format like that to store and transfer data between files.

why does the keyboard.is_pressed() function refuse to work when pressed?

i have less than 3 months of python programming under my belt but basically, i have a program that pulls values from the CoinGecko API indefinitely and creates processes so the functions that pull the data can run independently from one another, but id like for it to break its loop after i press the specified hotkey which is set to 'q'. whenever i press the hotkey, nothing happens and the loop just keeps running. i've tried using the keyboard.read_key() function, but that just stops my program from running until i press the q button, which causes the program to run the loop once and then close. i have no idea why the is_pressed() function refuses to work and id like some help from more advanced people
Piece of Code in question:
from multiprocessing.dummy import freeze_support
from pycoingecko import CoinGeckoAPI
import time
from multiprocessing import Process
from multiprocessing import Pool
import multiprocessing
import keyboard as kb
import psutil
cg = CoinGeckoAPI()
class CGCoin:
def __init__(self, coinname, coinid):
self.coinname = coinname
self.coinid = coinid
def pulldata(self):
while True:
wishtoquit = False
if kb.is_pressed('Q'):
print('ending after this loop')
wishtoquit = True
timestarted = time.asctime()
self.prices = []
self.daychanges = []
self.volumes = []
self.marketcaps = []
self.weekchanges = []
self.highs = []
self.lows = []
self.times = []
print(f'starting {self.coinname} reading at {timestarted}')
loops = 0
maxloops = 2
while loops < maxloops:
time.sleep(15)
coin = cg.get_coin_by_id(f'{self.coinid}')
time.sleep(5)
coinvalues = coin.get('market_data')
coinprices = coinvalues.get('current_price')
coinvolumes = coinvalues.get('total_volume')
mrktcaps = coinvalues.get('market_cap')
dayhigh = coinvalues.get('high_24h')
daylow = coinvalues.get('low_24h')
daychangepercentage = coinvalues.get('price_change_percentage_24h')
weekchangepercentage = coinvalues.get('price_change_percentage_7d')
coinprice = coinprices.get('usd')
coinvolume = coinvolumes.get('usd')
coincap = mrktcaps.get('usd')
coindayhigh = dayhigh.get('usd')
coindaylow = daylow.get('usd')
timepulled = time.asctime()
self.prices.append(coinprice)
self.daychanges.append(daychangepercentage)
self.volumes.append(coinvolume)
self.marketcaps.append(coincap)
self.weekchanges.append(weekchangepercentage)
self.highs.append(coindayhigh)
self.lows.append(coindaylow)
self.times.append(timepulled)
loops = loops + 1
print(loops)
timeended = time.asctime()
})
print(f'stopping {self.coinname} reading at {timeended}')
if wishtoquit:
print('ending loops')
break
time.sleep(5)
bitcoin = CGCoin('Bitcoin', 'bitcoin')
ethereum = CGCoin('Ethereum', 'ethereum')
if __name__ == '__main__':
freeze_support()
btcpul = Process(target=bitcoin.pulldata, name=bitcoin.coinname)
btcpul.start()
if anyone has any ideas or fully-functional workarounds id really like to hear them. id be extremely grateful for any help recieved
It looks like PyPi keyboard needs root permissions on linux.
You could just do kb.on_press_key("p", lambda _: sys.exit(0)) and just do a sys.exit(0) to end the script.
If you're running this in the terminal you should just be able to press ctrl+c to interrupt its execution.
ref: How to detect key presses?

How to “correctly” detect application name when changing focus event occurs with python xlib

I want to detect applications window name when changing focus event occurs with python xlib, so in the first step I use this code:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import Xlib.display
import time
display = Xlib.display.Display()
while True:
window = display.get_input_focus().focus
wmname = window.get_wm_name()
wmclass = window.get_wm_class()
if wmclass is None and wmname is None:
window = window.query_tree().parent
wmname = window.get_wm_name()
print "WM Name: %s" % ( wmname, )
time.sleep(3)
But I want a correct way, then I research about xlib events and find Input Focus Events and write this code:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import Xlib.display
from Xlib import X
def main():
display = Xlib.display.Display(':0')
root = display.screen().root
root.change_attributes(event_mask=Xlib.X.FocusChangeMask)
while True:
event = root.display.next_event()
#if event.type == X.FocusIn or event.type == X.FocusOut:
if event.type == X.FocusOut :
window = display.get_input_focus().focus
wmname = window.get_wm_name()
wmclass = window.get_wm_class()
if wmclass is None and wmname is None:
window = window.query_tree().parent
wmname = window.get_wm_name()
print "WM Name: %s" % ( wmname, )
if __name__ == "__main__":
main()
Sadly it's not work correctly especially in tabbed browsing on google chrome and firefox, so Is there a correct way for this situation?
Your code is almost right, but it misses two things:
rather than listening only to focus changes, it should also listen to window property events which include changes of WM_NAME property, that also happen when you cycle tabs in your browser.
rather than listening only in root window, it should listen to every window (that gets focused). You can attach the event handler the same way as you do with the root window.
That being said, here is a working sample:
#!/usr/bin/python3
import Xlib
import Xlib.display
disp = Xlib.display.Display()
root = disp.screen().root
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
root.change_attributes(event_mask=Xlib.X.FocusChangeMask)
while True:
try:
window_id = root.get_full_property(NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType).value[0]
window = disp.create_resource_object('window', window_id)
window.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
window_name = window.get_full_property(NET_WM_NAME, 0).value
except Xlib.error.XError: #simplify dealing with BadWindow
window_name = None
print(window_name)
event = disp.next_event()
#rr- As I just corrected elsewhere, you'll want to query both the current _NET_WM_NAME (UTF-8) and the legacy WM_NAME (non-UTF8) properties or the default xterm configuration will return no title.
I just posted a complete working example over on your Unix & Linux StackExchange question.
To avoid sending people on a cross-reference hunt, here's a copy of the code I posted there:
#!/usr/bin/python
from contextlib import contextmanager
import Xlib
import Xlib.display
disp = Xlib.display.Display()
root = disp.screen().root
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME') # UTF-8
WM_NAME = disp.intern_atom('WM_NAME') # Legacy encoding
last_seen = { 'xid': None, 'title': None }
#contextmanager
def window_obj(win_id):
"""Simplify dealing with BadWindow (make it either valid or None)"""
window_obj = None
if win_id:
try:
window_obj = disp.create_resource_object('window', win_id)
except Xlib.error.XError:
pass
yield window_obj
def get_active_window():
win_id = root.get_full_property(NET_ACTIVE_WINDOW,
Xlib.X.AnyPropertyType).value[0]
focus_changed = (win_id != last_seen['xid'])
if focus_changed:
with window_obj(last_seen['xid']) as old_win:
if old_win:
old_win.change_attributes(event_mask=Xlib.X.NoEventMask)
last_seen['xid'] = win_id
with window_obj(win_id) as new_win:
if new_win:
new_win.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
return win_id, focus_changed
def _get_window_name_inner(win_obj):
"""Simplify dealing with _NET_WM_NAME (UTF-8) vs. WM_NAME (legacy)"""
for atom in (NET_WM_NAME, WM_NAME):
try:
window_name = win_obj.get_full_property(atom, 0)
except UnicodeDecodeError: # Apparently a Debian distro package bug
title = "<could not decode characters>"
else:
if window_name:
win_name = window_name.value
if isinstance(win_name, bytes):
# Apparently COMPOUND_TEXT is so arcane that this is how
# tools like xprop deal with receiving it these days
win_name = win_name.decode('latin1', 'replace')
return win_name
else:
title = "<unnamed window>"
return "{} (XID: {})".format(title, win_obj.id)
def get_window_name(win_id):
if not win_id:
last_seen['title'] = "<no window id>"
return last_seen['title']
title_changed = False
with window_obj(win_id) as wobj:
if wobj:
win_title = _get_window_name_inner(wobj)
title_changed = (win_title != last_seen['title'])
last_seen['title'] = win_title
return last_seen['title'], title_changed
def handle_xevent(event):
if event.type != Xlib.X.PropertyNotify:
return
changed = False
if event.atom == NET_ACTIVE_WINDOW:
if get_active_window()[1]:
changed = changed or get_window_name(last_seen['xid'])[1]
elif event.atom in (NET_WM_NAME, WM_NAME):
changed = changed or get_window_name(last_seen['xid'])[1]
if changed:
handle_change(last_seen)
def handle_change(new_state):
"""Replace this with whatever you want to actually do"""
print(new_state)
if __name__ == '__main__':
root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
get_window_name(get_active_window()[0])
handle_change(last_seen)
while True: # next_event() sleeps until we get an event
handle_xevent(disp.next_event())
There's also a more heavily commented version in this GitHub Gist.

Categories

Resources