I am trying to build a Tkinter UI with a button where the user chooses a main file and based on information in that file, the script would get some information about some secondary files. Upon choosing the main file, I am trying to use the file path of the main file to get the file path of the secondary files. However, because I am calling a function "open_main_file()" twice, I get two dialog boxes where the user will have to choose the main file twice instead of once. How can I circumvent that?
My code looks like this:
import pandas as pd
from tkinter import *
from os.path import dirname
from tkinter import filedialog
root = Tk()
def open_main_file():
return filedialog.askopenfilename()
def parse_main_file():
return pd.read_parquet(open_main_file(), engine='pyarrow')
def get_some_ids():
return parse_main_file()['some_ids'].iloc[0]
def get_list_of_other_files():
other_files_path = dirname(dirname(dirname(open_main_file())))
list_of_other_files = []
for f in get_some_ids():
list_of_other_files.append(glob.glob(other_files_path + '/identifier=' + str(f) + '/*'))
return map(''.join, list_of_other_files)
myButton = Button(root, text='Open File...', command=get_list_of_other_files).pack()
root.mainloop()
try not to use a function in other functions. In this case, you are calling a function one time in another one, and one time in the main code. That is why you get file dialog 2 times. Use the returned item and give it to the next function. You can code like this:
import pandas as pd
from tkinter import *
from os.path import dirname
from tkinter import filedialog
root = Tk()
def open_main_file(): # This function is not necessary
return filedialog.askopenfilename()
def parse_main_file(main_file_path):
return pd.read_parquet(main_file_path, engine='pyarrow')
def get_some_ids(main_file_path):
return parse_main_file(main_file_path)['some_ids'].iloc[0]
def get_list_of_other_files():
main_file_path = filedialog.askopenfilename()
other_files_path = dirname(dirname(dirname(main_file_path)))
list_of_other_files = []
for f in get_some_ids(main_file_path):
list_of_other_files.append(glob.glob(other_files_path + '/identifier=' + str(f) + '/*'))
return map(''.join, list_of_constituent_files)
myButton = Button(root, text='Open File...', command=get_list_of_other_files).pack()
root.mainloop()
Related
I'm having trouble decoding an image when I import it from another file.
I have four .py files to make two buttons.
In the first, on line 21, the button works and brings the image, in the second, on line 28, which is imported from another file, it appears as a button but without an image. How can I resolve this?
lab.py
import tkinter as tk
import base64
from imagens import *
from cores import *
from widgets import *
class Janela(Images):
def __init__(self) -> None:
self.images_base64()
self.tamJanela()
def tamJanela(self):
self.janela_doMenu = tk.Tk()
janela = self.janela_doMenu
# janela.state('zoomed')
janela.title('Disk Gás Gonçalves')
janela.configure(background=preto_claro)
janela.geometry("%dx%d" % (janela.winfo_screenwidth(), janela.winfo_screenheight()))
# Here the code works ###############################################################
self.img_icoName = tk.PhotoImage(data=base64.b64decode(self.editUser))
self.rotulo_nome2 = tk.Button(master=janela, image=self.img_icoName, activebackground='#00FA9A', bg='#4F4F4F',
highlightbackground='#4F4F4F', highlightcolor='#4F4F4F')
self.rotulo_nome2.grid(row=0, column=0)
# Here the code does not work #######################################################
# I'm importing from widgets.py #####################################################
Botoes(janela)
janela.minsize(1200, 640)
janela.mainloop()
Janela()
widgets.py
import tkinter as tk
import base64
from imagens import *
from cores import *
class Botoes(Images):
def __init__(self, local) -> None:
self.images_base64()
self.local = local
self.bt()
def bt(self):
self.img_icoName = tk.PhotoImage(data=base64.b64decode(self.editUser))
self.rotulo_nome2 = tk.Button(master=self.local, image=self.img_icoName, activebackground='#00FA9A', bg='#4F4F4F',
highlightbackground='#4F4F4F', highlightcolor='#4F4F4F')
self.rotulo_nome2.grid(row=1, column=0)
cores.py
preto_claro = '#4F4F4F'
verde_médio = '#00FA9A'
vermelho_salmão = '#FA8072'
azul_seleção = '#F0FFFF'
verde_limão = '#00FF00'
branco_gelo = '#EDEBE6'
imagens.py
import base64
class Images:
def images_base64(self):
self.addUser = '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'
self.editUser = 'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFiVAABYlQHZbTfTAAAAB3RJTUUH5gkWFhApZHBt8gAADaRJREFUaN7NmXtwVNd9x7/n3Nfu3ae0Wu1qtXpLICNhG/AjDrEhAQS4pHadGbedcRPHIAxx/ODRJs6jbrHjtHHrqRPjENu1HXDbqRvbk+IgwHVcB49pDY4BSwgJCb2FHvvevXf37t57T/8QUAN6rBB0+pu5M3tn73l8fr/fOfd7fpfgKthrm9dO/ofBAbyO+1/YfzWGmdbIXCZPCYFumuB5DrLVigK3C7fefCNswRK8/3YLxkJhpNMZMMZAKcX9P2/5/wPy2uY7QQiDYZhwOOw49lm7UBbwl9ps1nmSJFUKPF8IgMvl9DElrR6PRGKtpQG/mkikIAg8vrnr2kRnViCvbV6L8VAYvmIvBofOisFS/xc8hQX3ejwFywrczjJZlmVBEHgCEC2bzUUisdDw2bH9o2Pjz61bs+L4W3v3QxSEawKTN8hrm9cikUzB6ylEIpkK+H3ehyvKS78RDJaUuBwO8AJ3WXemaSIajeFU55ljPb392+rn1fz2ROspCIIA0zSvaqrlBbLnoTvx0cfHcPttN0FNZ6rKgiU/WVBf90eBkmKOchzA2DQjEKSSKRz7rP337R1d65tf2n3sjW0PQVFUUErBcTz+7Pm9cwbh8nnoD5fUoKzUj6SieCrKS39y4/UL/iQQ8FFC8guoKEmQrVa/YRiLjv/m38uUlKqNjoVGrFarSSnB20dO/9+A3LWkBi//cj9Z9eWbHmxsmP9osNSfV7vPmyxbid/nDXq9nmUWSWqilGRD4cgxQeCNu2+uw6+Pdl1bkFc3rYEoCmi4rry2tqbix/PrqgMcN2sOgBDwAg+7TYa3qNDFGG5RVLWzvq6mfTwUmTMInXl8gvp5tXC7nF8J+H31oijOehBdN6AqaTDTBBiDIAiorizz+IqL1h8+8mlBvik6JxDTZNjb8p7kdDiWFrhds6MgBLmcjq7eXrT1deFM/wByOR0Agyxb4S3yLHY6HPMtFmlqdXC1QAglcLudDrvNWitZxOl3qEsgVEVFZ08P+BIJDU0LYBZRdPf3wdANEErhdNrdVqtU53DY5wSRFwglBJIg2ERRLLhobRAy+QVA07IYHDyLjsFeOOcXoHpJFWSnjJrFVWBuDiNjIYAQSKIoCoLgq6+rnjMIP7NjCQghHCFkgoIApmEikVSgptMwDOPCc6ZpIp3VkDY0WLxW1C6phcNjBxgAxkB5DoH6EvR/1Ae/7gXHcYRSKlfftx6HPjpybUFMk0HXjXRO11PMZNBNA939/cgIOdg8NvAiBzBMCEOOg9tRiDKPA1a7BYTSi1ORMcguGUwEsloWpmkyZpqZwTd2X/uImKaJlKIm0un0QE7PLY7GEtCdDAtuuw6CKPyvNmC4+Ddjk64nylFQgUI3DGQympbN5gZPtJ4CuXIhPtHvTA8QAjz+9lE1mVKPp1IqUqoKT7AQgiRMTNQ8d136ewYzDBPxRDKsqulTiUQKeW4hVw7iqQN+9edfY0omeTwUDismM0D5GZvN6J1MJoNwNHI6Yyh9OjSULDLm1OWMqSU5GURnRC4gzlURNWy1ic45HMfOcQAIhSMwbKnqeV9yNlIIH+RymTn1OXNqgcDIkiK3z3mHxcvT8VBkTvlMyMT2PJ4IwV9XUC4Iwhcq51fMzTP5gACAaZgZxliioFSGKeXA8n0pTmE5IwfZz0Oy87ppmNHQaAhzVSkzgjDGEItEw2pSOQROR+A6BwQLwVxWpysgoKjSBjWpDGQz2n8nY/E8XToHEPBAoDxopBV1d2Qs9CmjWdAZV9Y0RgDeCqQSMS0eib2ajCfa9KwOpl9rEAPIahqamve3Rscjjyai8cNzSi0G5LRccvzs6N+qKeVnDrdLBwFWP3hgTiAz+nZ18wEceHE19u9aheLS4KFkLLY7l83enE/bycw0DBiG3p6IRnbaXe4YLwgwcvmF46PlywE64fvzziSETMiffDpYvfEAKMchGYshq6VPKsl4LG8V/HkjBFomjXQqeVJJxOLMNGFkc2hqnrmqsu9r96I8FQOjFLdt3IjE6KglNjQkeoLBCXmU/yQALZOGkky2xUJjn2bSKma91TCGWHhcTSVi7zbc9EWNEoqmjTOn1NNP/B3WvvkG3lm6FrZYxP3Jnj0PBhcufKXshht+ER8buyenaZa8z6yv7+3GfetqsPCmW9NnB3qZxWptcroLxbxPd4RASSXQ33nqvdDI8LO5rKYwBrz+Tve0zb77zEv4q+8/jB88/QJGJNkrO51PzispftxXVbnIVVx8IycIX8lpmjKrw/d9X61BeHQESjLeYxpmsUW2LbY5nDNH9VxK9XW2nxkd7PuO2+NtS6tJrNn07rTNnnr2Gdy67dvYbS9BQtU8wWDpk9K8+mZB4MUATyBKEiSbzZZJJhtmBfL6O93YcG8DKM9n06nUoJpKrON5wSXbHKCTFSTORUtJxNHT0Yqz/T2vDp458xIvCIxyFK/vnToa77/8ZXz9Wy/in//eDSWTKQqUlu+4fmHjhnkLFghDjCIZjsDLcuAohRKJyLN+DWW17HmBkhJELhsLD6O7/TjGhweRy2oXToqMMaRiUQx0d6Cvuw2MaeB4LvGNp75nUo5i9caDU45x8KXVqFn/W+z86XeQTGlFPn/5UzcsbGyuLC8TLJKImoYGjNVfj1ZqRVpRoSnK7/PaQrftPARKKQzDwMEcRZV0HHX6L01BKEWBtwBaRkN4tBeR8WEUFJVAEEUkYxGkEmGIFgFujwtaJgM6OsZ27b8Bw8yPrc//ABPykeHZb9/+OYg1WLXhe/iPf1yL+XzYU1Z1y46YrfaBwkKPQCkFYwyiIKC2oRGnslmMf9Df7otGn+CnB/gQqkLAmAlR4vHJx91cdU3A18WWVKcl+ZY7zMMuQgisNhkW2YpMOoNoaACMMfACD7fXDZ6fGEJLM4ybtUvO9Kl3ZzWpK5lI9d2+vDF5srUfW372OxBKsEZ8Cqs2/CXefXkHMmrK4w3U7micH9iQJIrQ2nsctPpGOOy2iczIakjo5ulet3/7Xx88eGDKLWfb84egGyasVhGjI1GLp8h5s9Ml3+Vy25c5nbYqu0V3+KN7hEpPlAgWy+Xaa8LZ54whPJ5ED7fOjEmL0qmkEorHlWPxmLIvmVBb7vv68oF//ZcPMa9WRM3gE1CVlKe4pGxHVX1jc3FpmUAIwekhE63DAVTULAIhDMc/a+vo6up+7Efb1+/ftXnb5JXG7S98CMMw8fQjd+Ddwz2NgaDnh5VVJT+sqQ00lZV7A0Vel+xwuziDSISFT0C2chPn80mMEEBNKhjXqyHW3EXcngLRU+RyF3ld9U6nvFoQ+Ns/OdqtJxNqdyD7QVZS2y+DAACPk4AnSbSfiaFnYOx0b++ZLU9uXd+S4T1IuTyXg0xAGBgfi/GfdkXuKasofm5efdkflAa9dptNAv3chInVj0xGhxntgEUEKMefr7pgQjmYUBIpjKpe6BV/CiJ7ATYhK0SRh9Nl4wo9zqBkEVeajPj05NmzC/zxrVX1jRuLS8uFi95RhEDmFIT6WzvbuqNbdmx/ZV/GkgMRJPz48c0Xg2zbeQimYSIUivPlFb77q2tLnqmbH6xxumRM+uIjFMRZjbThgBoZgpGOw9A16Nks0oqGaNxEmDRAL78X1B6cNGKCwMFV4BBtgraoOPdfTQvr/cuLS8vFSyEyioLejrYOZaRtyzcfeqHlF4XtUFgRnv6Lb13I5AsQhmHiHx5Zhu++ePiPq2sDz9XUBXyiyOclq1gmDBY/DZIZATFzYIILzF4J4qgE4cWpzy8EYFoCfP+bqHaOwldaiskgejpaO4d6uh5duX7f/rd23g3CS7hn0xsXLUkAwGM//U9YZQu0THZxVXXJnvqGigUWi5C/Nvx8KWiy+5kgXKPwBaaGGO7pemzF+n0tLT9fCY7jL5P99Hw0KOUwPhqzeYpcj1RU+WYHcX7CbJr7qwGxawU4npv07MKfawOb3QqOo0tLAp51Lrf9ilR63kYAlomD638T1e6xySHUSyOxAhzPT6kIKDBRFu1o7xddbts9Xp/bQ+ncv1dMH4k4+P5foWaqSKgKek61dg5dmk7TyBq6feeH4DgO3mJ3wF1gX2q3Wa5pNEwtBf3UPyEg9MAfDE4N0dv12MoLEBxWP3hw2n6pIiqwWERYrVKd0ymXcfwVfFabRTTU/iOwx04gpyaRVpQpI7HygX0tLbtWTqTTDBAAQOWcDKdLhigJlVbZYqN06k8fc70MTQFGjqLC74FMBAx0nEQqEQcoPQ/RNdTTtWXlRemUX1GCJyBwOGVEIylHJJTIZLM6mXMFbtJoUCDaJtZiRHTYCkGoHTQRw3B3JzyBUowND3YPnuna2tTcsu832krwPJc3BHBu1+rrGUUup7/T3TXcdS5lrzIIQSatSlz/W48uXC5/ieMoTAbYbQ4kR9NoO3K0K5tVtjY3t+zd+/wKkDzWxKQgVqsEwzA6RUno5Lg5lvwmsYH2j3Hid//WIEqyX6ZePLDGAso0DI1Gh0fHo+9ntOTLgYKTH+zcuRKUUty5aXYQE666xra8aR0qPTnSMSp+3zCxg6Mk98V66+lFZdreeCLx65FQ/MSyW4Oqkk5BFHis3XRlhbprDrJ0xTpwBL6sQd5iQICAvWLo+pss2dWx/qt1hpHTYDACSoCH/+a9Kx7nfwAPPztG5sk4owAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wOS0yMlQyMjoxNjoxNyswMDowMOu8Z3oAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDktMjJUMjI6MTY6MTcrMDA6MDCa4d/GAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='
I tried to create a button by importing the base64 image from another file.
There are two buttons in the application, one works and the image appears, the other does not work and the image does not appear. I would like to make the second one work.
All the code will generate this image. The bottom button that doesn't show the image is in the widgets.py file
I don't know why, but when I import it, it doesn't work.
Thank you in advance for your attention and I apologize if something was wrong or out of standard, my English is not very good.
It is because there is no variable referencing the instance of Botoes(), so it will be garbage collected (so as the image inside it).
Just use a variable to store the instance of Botoes():
class Janela(Images):
def __init__(self) -> None:
self.images_base64()
self.tamJanela()
def tamJanela(self):
self.janela_doMenu = tk.Tk()
janela = self.janela_doMenu
# janela.state('zoomed')
janela.title('Disk Gás Gonçalves')
janela.configure(background=preto_claro)
janela.geometry("%dx%d" % (janela.winfo_screenwidth(), janela.winfo_screenheight()))
# Here the code works ###############################################################
self.img_icoName = tk.PhotoImage(data=base64.b64decode(self.editUser))
self.rotulo_nome2 = tk.Button(master=janela, image=self.img_icoName, activebackground='#00FA9A', bg='#4F4F4F',
highlightbackground='#4F4F4F', highlightcolor='#4F4F4F')
self.rotulo_nome2.grid(row=0, column=0)
# need a variable to store the instance of Botoes
# to avoid garbage collection
botoes = Botoes(janela)
janela.minsize(1200, 640)
janela.mainloop()
Result:
I created a python script (NoShowCalc.py) that automates data cleaning and analysis with 3 selected excel files (booked_file_path, arrived_file_path, and vlookup_file_path). However, I want this all to be executed through a GUI, so I started a separate (GUI.py) script to create an interface with browse buttons that will get those file path names, then that will get me what I need to execute the NoShowCalc.py script. Once those excel files are selected, another button is there to execute the NoShowCalc.py script. However, I did it and it worked! But I have no idea what I changed and now the two different py files are not connecting.
Here's the script in the NoShowGUI.py script:
def open_file():
browse_text.set('Loading...')
booked_file_path = askopenfile(parent=root, mode='rb', title='Choose a file', filetype=[('CSV file', '*.csv')])
if booked_file_path:
read_csv = (booked_file_path)
browse_text.set('Loaded')
def run():
os.system('NoShow_Calc.py')
calculate_text.set("Calculating...")
#Calculate button
calculate_text = tk.StringVar()
calculate_btn = tk.Button(root, textvariable=calculate_text, command=lambda:run(), font='Calibri', fg='black', height=1, width=15)
calculate_text.set("Calculate No Show")
calculate_btn.grid(column=2, row=9)
These are the first lines in the NoShowCalc.py script:
import pandas as pd
booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
vlookup = pd.read_excel(vlookup_file_path)
The error that keeps popping up is NameError: name 'booked_file_path' is not defined. I don't get how it ran before and now this error is popping up as it can't speak to the other py file anymore. What did I do wrong?
If you run script using os.system() or using module subprocess then you can't use variables from other script. They runs as separated processes and they can't share variable (or data in memory)
You can only send some text values as arguments
os.system('NoShow_Calc.py ' + booked_file_path)
and then you can get it inside NoShow_Calc using sys.argv
import pandas as pd
import sys
booked_file_path = sys.argv[1]
booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
vlookup = pd.read_excel(vlookup_file_path)
If you need other variables then you have to send other values in the same way
os.system('NoShow_Calc.py ' + booked_file_path + ' ' + other_filename)
and
booked_file_path = sys.argv[1]
other_filename = sys.argv[2]
# etc.
But using os.system() you can't send result booked, arrived, vlookup from NoShow_Calc to NoShowGUI.
You could do it with subprocess but it can send it only as text - so NoShow_Calc would have to use print() to display all result and NoShowGUI would have to parse this text to expected structure - ie. list, dictionary, DataFrame
Better you should use import to load code from NoShow_Calc.py and then all code runs in the same process so all code has access to the same variables - and it doesn't need to convert to text and back from text.
To make it better I put code in function
import pandas as pd
def my_function(booked_file_path, arrived_file_path, vlookup_file_path):
booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
vlookup = pd.read_excel(vlookup_file_path)
return booked, arrived, vlookup
and then in NoShowGUI you can import it and use like any other function
from NoShow_Calc import my_function
booked, arrived, vlookup = my_function(booked_file_path, arrived_file_path, vlookup_file_path)
EDIT:
I made minimal working code. I reduced it to only one filename.
NoShow_Calc.py
import pandas as pd
def calc(booked_file_path): #, arrived_file_path, vlookup_file_path):
booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
#arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
#vlookup = pd.read_excel(vlookup_file_path)
return booked #, arrived, vlookup
NoShowGUI.py
import tkinter as tk
from tkinter.filedialog import askopenfilename # instead of `askopenfile`
# adding directory with this script to `sys.path` before `import NoShow_Calc`
# to make sure that `import` will search `NoShow_Calc.py` in correct folder even when GUI will be run from different folder
import os
import sys
HOME_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(HOME_DIR)
import NoShow_Calc
print('HOME_DIR:', HOME_DIR)
def select_filename():
global booked_file_path # inform function that it has to assign value to external/global variable
text_log.insert('end', 'Selecting ...\n')
# use `askopenfilename` instead of `askopenfile`
# because I need only filename, not opened file (pandas will open it on its own)
booked_file_path = askopenfilename(parent=root,
title='Choose a file',
#initialdir='/home/furas',
filetypes=[('CSV file', '*.csv')])
if booked_file_path:
text_log.insert('end', f'Selected: {booked_file_path}\n')
else:
text_log.insert('end', f'Not selected\n')
def run():
text_log.insert('end', "Calculating...\n")
if booked_file_path is None:
text_log.insert('end', "File booked_file_path not selected !!!")
return
#elif arrived_file_path is None:
# text_log.insert('end', "File arrived_file_path not selected !!!")
# return
#elif vlookup_file_path is None:
# text_log.insert('end', "File vlookup_file_path not selected !!!")
# return
else:
root.update() # force tkinter to update text in text_log at once (not when it exits function `run`)
result = NoShow_Calc.calc(booked_file_path)# , arrived_file_path, vlookup_file_path)
text_log.insert('end', "Result:\n")
text_log.insert('end', str(result.head()) + "\n")
# --- main ---
booked_file_path = None # default value at start (so in `run` I can check `None` to see if I selecte filename)
#arrived_file_path = None
#vlookup_file_path = None
root = tk.Tk()
text_log = tk.Text(root)
text_log.grid(column=0, row=0)
select_btn = tk.Button(root, text="Select File Name", command=select_filename)
select_btn.grid(column=0, row=1)
calculate_btn = tk.Button(root, text="Calculate", command=run)
calculate_btn.grid(column=0, row=2)
root.mainloop()
I'm currently working on a program that displays variables line by line as code executes from a file (think trace tables). I'm able to get it working fine when the code is encased within a function inside the program itself but when I import the same code, it tracks new variables that I don't want to track (as they don't appear in the actual script). Is there any way I can isolate the variables specific to the program? (it'll also be useful for when I'm ignoring variables from pulled libraries in Python).
Here's my program so far:
import sys
import dis
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
line_record = [] #where data on variables will be stored line by line
def trace(frame, event, arg_unused): #tracing function
global line_record
relevant_locals = {}
temp_vars = frame.f_locals.copy()
for k,v in temp_vars.items():
if not k.startswith("__"):
relevant_locals[k] = v
line_record.append([frame.f_lineno, relevant_locals])
return trace
def print_results(v_list):
print_record="" #variable which holds the formatting of the data
for item in v_list: #iterating for data in each recorded line
print_record += "Line " + str(item[0]) + "= "
if item[1]=={}: #catching lines with no variables
print_record += "no variables"
else:
for key in item[1]: #iterating through each variable to fetch associated data
print_record += str(key)+"="+str(item[1].get(key,"error"))+"|"
print_record += "\n"
return print_record
root = Tk() #creating the main window
root.title("frame")
root.iconbitmap("c:/Users/hamza/Documents/Other/Python/GUI/6 images/apple.ico")
root.filename = filedialog.askopenfilename(initialdir="/", title="select file",filetypes=[("python files","*.py")]) #import python files through tkinter dialog box
user_code = compile(open(root.filename, "rb").read(), root.filename, 'exec') #compiling imported code in order to use later in project
sys.settrace(trace)
exec(user_code)
sys.settrace(None)
print(print_results(line_record))
root.mainloop()
And for reference (if needed), my test code is:
a = 1
b = 2
a = a + b
If you need any more information please don't hesitate to ask, I'm happy to clarify, thanks.
I'm using filedialog with tkinter to browse a file in my Python application. When I click on 'browse' I have this message :
objc[84539]: Class FIFinderSyncExtensionHost is implemented in both
/System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit
(0x7fff99d17cd0) and
/System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride
(0x1103dfcd8). One of the two will be used. Which one is undefined.
Here is my "browse" function
def select_input_file(self):
global inputFileName
self.inputFileName = fd.askopenfilename(initialdir = "./",title = "Select file",filetypes = (("all files","."),("txt files","*.txt")))
if(lb.size() == 0):
lb.insert(END,self.inputFileName.split("/")[-1]) #Inserts txt filename in listbox.
else:
lb.delete(0)
lb.insert(END,self.inputFileName.split("/")[-1])
How can I fix this ?
Am a new in GUI programming and I am trying to make a GUI for one of my python parser.
I know that :
Tkinter is single threaded. Screen updates happen on each trip through the event loop. Any time you have a long running command you are preventing the event loop from completing an iteration, thus preventing the processing of events, thus preventing redraws.
My program call a big function that takes about 5 minutes to be ran entirely. So I guess the only solution is tu use thread for the long running command.
BUT, my long running command in already threaded so I don't really know how to proceed.
--> As soon as I click on BUT1 in the GUI, the program freeze until the function is entirely done. I'd like to run this function in the backgroung, so the program will not freeze.
--> I'm not looking for a complete solution but if someone can put me on a good track, it will be wonderful !
Main.py -> The GUI
Module_1.py -> The function that we call by clicking on the button BUT1
Thank you in advance !
Here is Main.py --> the GUI
#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import *
import sys
import tkMessageBox
import tkFileDialog
import Module_1
import csv
from time import strftime, gmtime
DATE = strftime("_%d_%b_%Y")
class App:
def __init__(self, master):
self.frame = Frame(master, borderwidth=5, relief=RIDGE)
self.frame.grid()
class IORedirector(object):
def __init__(self,TEXT_INFO):
self.TEXT_INFO = TEXT_INFO
class StdoutRedirector(IORedirector):
def write(self,str):
self.TEXT_INFO.config(text=self.TEXT_INFO.cget('text') + str)
self.TEXT_HEADER = self.text_intro = Label(self.frame, bg="lightblue",text="THIS IS \n MY SUPER PROGRAM")
self.TEXT_HEADER.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
self.MENU = Frame(self.frame, borderwidth=5, relief=RIDGE, height=12)
self.MENU.grid(row=1, column=0, sticky=N)
self.button = Button(self.MENU, text="QUIT", bg="red", command=self.frame.quit)
self.button.grid(row=4, column=0)
self.BUT1 = Button(self.MENU, text="BUT1", command=self.BUT1)
self.BUT1.grid(row=0, column=0,sticky=W+E)
self.TEXT_INFO = Label(self.frame, height=12, width=40, text="SOME TEXT", bg="grey",borderwidth=5, relief=RIDGE)
self.TEXT_INFO.grid(row=1, column=1, sticky = N+W)
sys.stdout = StdoutRedirector(self.TEXT_INFO)
def BUT1(self):
self.BUT1.config(text="RUNNING")
self.TEXT_INFO.config(text="BUT1 LAUNCHED")
Module_1.main("BUT1")
## HERE WE NEED TO RUN THE FUNCTION
## THE PROGRAMM FREEZE HERE UNTIL THE FUNCTION IS ENTIRELY RUN
self.TEXT_INFO.config(text="BUT1 FINISHED")
self.BUT1.config(text="DONE")
root = Tk()
app = App(root)
root.mainloop()
And here is Module_1.py --> contain the big function
#!/usr/bin/python
# -*- coding: utf-8 -*-
import Queue
import threading
import urllib2
import time
from bs4 import BeautifulSoup as soup
from urllib2 import urlopen
import re
import os
import random
import sys
import logging
import csv
from time import strftime, gmtime
import os
import random
import shutil
import sys
import re
import logging
from threading import RLock
from time import strftime, gmtime
import csv
import urllib
from urllib import urlretrieve
from grab.spider import Spider, Task
logging.basicConfig(level=logging.CRITICAL) # Loggin to DEBUG / INFO
log = logging.getLogger()
DATE = strftime("_%d_%b_%Y")
class SPIDER1(Spider):
initial_urls = ['URL_THAT_I_NEED_TO_PARSE']
def __init__(self):
super(SPIDER1, self).__init__(
thread_number=20,
network_try_limit=20,
task_try_limit=20
)
self.result = {}
def task_initial(self, grab, task):
for opt in grab.css_list("select[name='Template$TestCentreSearch1$SubRegionList'] option")[1:]:
grab.set_input('Template$TestCentreSearch1$SubRegionList', opt.attrib['value'])
grab.submit(extra_post={
'__EVENTTARGET': 'Template$TestCentreSearch1$SubRegionList'
}, make_request=False)
yield Task('parse', grab=grab, country=opt.text_content())
def task_parse(self, grab, task):
log.info('downloaded %s' % task.country)
city_gen = (x.text_content() for x in grab.css_list(".TestCentreSearchLabel+br+span"))
title_gen = (x.text_content() for x in grab.css_list(".TestCentreSearchTitle"))
id_gen = (x.attrib['href'][-36:] for x in grab.css_list(".TestCentreSearchLink"))
for x in zip(city_gen, title_gen, id_gen):
self.result[x[2]] = {
'country': task.country,
'city': x[0],
'name': x[1],
'id': x[2],
'price':'',
'currency':'',
'fee':''
}
yield Task('info', 'URL_URL=%s' % x[2], id=x[2])
def task_info(self, grab, task):
for label in grab.css_list(".TestCentreViewLabel"):
if label.text_content().strip()=="Test Fee:":
fees = label.getnext().text_content().strip()
self.result[task.id]['fee'] = fees
price = re.findall('\d[\d\., ]+\d',fees)
if price:
price = re.findall('\d[\d\., ]+\d',fees)[0]
self.result[task.id]['price'] = price.replace(' ','').replace(',','.')
currency = re.findall('[A-Z]{2,3}[$|€|£]?',fees)
if not currency:
currency = re.findall('[$|€|£]',fees)
if not currency:
currency = fees.replace(price,'').strip().replace(' ','')
if isinstance(currency,list):
currency = currency[0]
self.result[task.id]['currency'] = currency
#log.info(' %(price)s %(currency)s - %(fee)s ' % self.result[task.id])
break
def dump(self, path):
"""
Save result as csv into the path
"""
with open(path, 'w') as file:
file.write("ID;Country;State;City;Name;Price;Currency;Original Fee\n")
for test_center in sorted(self.result.values(), key=lambda x: "%(country)s%(city)s%(name)s" % x):
file.write(("%(id)s;%(country)s;;%(country)s;%(name)s;%(price)s;%(currency)s;%(fee)s\n" % test_center).encode('utf8'))
def main(choice):
parser, path, name = None, None, None
def run(name,parser,path):
log.info('Parsing %s...' % name)
parser.run()
parser.dump(path)
log.info('Parsing %s completed, data was dumped into %s' % (name, path))
log.info(parser.render_stats())
if choice == "NONE":
# DO NOTHING
# HERE I'D LIKE TO HAVE ANOTHER CALL TO ANOTHER THREADED FUNCTION
elif choice == "BUT1":
run('Function1',SPIDER1(),'C:\LOL\Output1'+DATE+'.csv')
So by clicking on BUT1, we run the main("BUT1") function contained in the Module_1.py file with argument BUT1 that launch -> run('Function1',SPIDER1(),'C:\LOL\Output1'+DATE+'.csv')
And then the program freeze until the parser has finished is work .. :)
The problem is simple: BUT1 won't return until the call to main returns. As long as main (and thus, BUT1) doesn't return, your GUI will be frozen.
For this to work you must put main in a separate thread. It's not sufficient that main spawns other threads if all it's doing is waiting for those threads.
If you call root.update() occasionally from the BUT1 function, that should prevent the GUI from freezing. You could also do that from a python thread with a fixed interval.
For example, updating every 0.1 seconds:
from threading import Thread
from time import sleep
self.updateGUIThread = Thread(target=self.updateGUI)
def updateGUI(self):
while self.updateNeeded
root.update()
sleep(0.1)
After the big function completes you can set self.updateNeeded to False.