Python - filesystem link and/or selectable text - python-3.x

How do I put a filesystem link and/or selectable text in the output Tkinter label?
Basically, I would like the user to be able to click on the folder that comes with the message "NO TRANSMITTAL", or at least copy and paste from the Tkinter window.
Also, I know this code can be much better looking, so please do not save any advices :):)
Thanks in advance.
Code below.
import os
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
gui = Tk()
gui.title("MY SCRIPT")
list_of_folders=[]
out_folders=[]
substring_transmittal="Transmittal"
current_folder=('')
substring_drawings_0='.pdf'
def getFolderPath():
folder_selected = filedialog.askdirectory()
folderPath.set(folder_selected)
def doStuff():
folder = folderPath.get()
final_print=("Checking for Transmittal in %s" %(folder))
for path, dirs, files in os.walk(folder):
list_of_folders.append(path)
for i in list_of_folders:
if '6_Out' in i:
out_folders.append(i)
else:
pass
for o in out_folders:
os.chdir(o)
current_folder=os.getcwd()
a=os.listdir(current_folder)
string_check_transmittal = list(filter(lambda x: substring_transmittal in x, a))
string_check_drawings_0 = list(filter(lambda x: substring_drawings_0 in x, a))
string_check_drawings_1 = list(filter(lambda x: substring_drawings_1 in x, a))
if string_check_transmittal:
out=str(current_folder[len(folder):])
final_print += "\n%s ---> Transmittal OK" %(out)
else:
if string_check_drawings_0:
if string_check_drawings_1:
out=str(current_folder[len(folder):])
final_print += "\n%s ------ NO TRANSMITTAL ------" %(out)
for i in a:
print(' ',i)
out=i
final_print += "\n %s" %(out)
else:
pass
else:
pass
string_check_drawings_0 = ''
string_check_drawings_1 = ''
display_text.config(text=(final_print))
folderPath = StringVar()
a = Label(gui ,text="Enter name")
a.grid(row=0,column = 0)
E = Entry(gui,textvariable=folderPath)
E.grid(row=0,column=1)
btnFind = ttk.Button(gui, text="Browse Folder",command=getFolderPath)
btnFind.grid(row=0,column=4)
c = ttk.Button(gui ,text="Check", command=doStuff)
c.grid(row=4,column=0)
d = ttk.Button(gui ,text="Exit", command=gui.destroy)
d.grid(row=4,column=4)
display_text=Label(gui, borderwidth=3, justify=LEFT)
display_text.grid(row=5,column=0,padx=5)
gui.mainloop()

Related

Python, selecting a specific file

I need to select a specific file, after specifying the number of this file in "if"...
Instead of "MTS.txt " we need the full path to the selected file using a digit!
I have not found any information about this on the Internet. Perhaps he made up his request badly!
from email import message
from click import clear
import pywhatkit
import pyfiglet
import os
import time
directory = 'MTS/'
# files = os.listdir(directory)
f = True
while (f==True):
def main():
os.system('CLS')
# print(files)
mtstxt = pyfiglet.figlet_format("Wa Helper", font = "smslant")
print(mtstxt)
def send_message_inst():
mobile = '+7' + input(' Номер: +7')
with os.scandir(directory) as files:
for i, file in enumerate(files):
print(' ', i + 1, file.name)
nof = os.listdir(path="MTS/")
# print(len(nof))
while True:
tarif = int(input(' Вариант: '))
if tarif >= 1 and tarif <= int(len(nof)):
msg = open("MTS.txt", encoding='UTF-8')
message = msg.read()
msg.close()
break
else:
os.system('CLS')
print(mtstxt)
print(' Номер:', mobile)
with os.scandir(directory) as files:
for i, file in enumerate(files):
print(' ', i + 1, file.name)
print("\033[31m{}\033[0m".format(" Ошибка - неверный вариант!"))
pywhatkit.sendwhatmsg_instantly(phone_no=mobile, message=message)
send_message_inst()
os.system('CLS')
sndtxt = pyfiglet.figlet_format("Sent!", font = "smslant")
print(sndtxt)
time.sleep(5)
if __name__ == '__main__':
main()
else:
break

Unable to bind function after pickling - tkinter

I have simple code which creates two fields by the press of a button. There are two other buttons to save and load back the entry fields created. I have used the bind function to bind field A and field B. Pressing the Enter button on field A after entering a number will print out its value multiplied by 5 in field B. At this point the bind function works perfectly.
When I create three entry fields and save the progress without entering any inputs and compile the program, then load the file, the bind function does not seem to work. It seems to work only for the last field created. My code is as follows. I tried my best to simplify the code.
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfile
from tkinter import messagebox
import pickle
class Test(Frame):
def Widgets(self):
self.button_add = Button(self, text = "Add", command = self.add)
self.button_add.grid(row=0, column =2)
self.button_save = Button(self, text = "save", command = self.save)
self.button_save.grid(row=0, column =3)
self.button_load = Button(self, text = "load", command = self.load)
self.button_load.grid(row=0, column =4)
def add(self):
def test(event):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
self.field_A.append({})
n = len(self.field_A)-1
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
n = len(self.field_B)-1
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
def save(self):
for n in range(len(self.field_A)):
self.entry_A.append(self.field_A[n].get())
self.entry_B.append(self.field_B[n].get())
fname = asksaveasfile(mode = "w", defaultextension = ".est")
data = {"fields": len(self.field_A), "entries_A": (self.entry_A),"entries_B": (self.entry_B)}
with open(fname.name, "wb") as file:
pickle.dump(data, file)
def load(self):
def test(event):
print("Why is the value of n always equal to", n, "?")
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
fname = askopenfilename(filetypes = (("Estimation Files (est)", "*.est"),))
location = fname.replace("/", "\\")
if location:
with open(location, "rb") as file:
data = pickle.load(file)
for n in range(data["fields"]):
self.field_A.append({})
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].insert(0, data["entries_A"][n])
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
self.field_B[n].insert(0, data["entries_B"][n])
def __init__(self,master = None):
Frame.__init__(self, master)
self.field_A = []
self.field_B = []
self.entry_A = []
self.entry_B = []
self.grid()
self.Widgets()
root = Tk()
app = Test(master = None)
app.mainloop()
You need a "closure". You can make a closure in python with the functools.partial function.
from functools import partial
def test(n, event=None):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
#other code ...
self.field_A[n].bind("<Return>", partial(test, n))
Both of your test() functions are accessing a variable n from the enclosing function. In the case of add(), there is no loop; n has a single value. Each Entry's test() gets its own n, because they were bound by a distinct call to add(). In load(), however, you are looping over n values; each test() is referring to the same n, which will have its final value by the time that any binding can possibly be invoked. The other answer gives a reasonable way to give each instance of test() its own personal n, so I'm not going to repeat that here.

Python watchdog module duplicate events (edit: was not an watchdog issue)

I am creating a python script that will identify changes to a log file and print some data from the new logs.
I use watchdog to create an event handler and everything seems to work fine except from that, I get duplicate events every time I modify the file. I checked creation and delete, they both work as expected and trigger one time.
I have read the similar question which explains having a created and a modified event when I save a file but this is not my case. I just get two modification events.
Here is my code:
import os, sys, time
import subprocess
import threading
import win32print
from tkinter import filedialog
from tkinter import *
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Handler(FileSystemEventHandler):
# docstring for FileSystemEventHandler
def __init__(self, observer, filename, dirname):
# super(Handler, FileSystemEventHandler).__init__(self,)
self.observer = observer
self.filename = filename
self.dirname = dirname
print("Handler filename = " , self.filename)
print("Handler dirname = " , self.dirname)
def on_modified(self, event):
if self.filename == event.src_path:
print("The file was modified")
print (event.src_path)
# go get the last line and print the data
# try:
# hJob = win32print.StartDocPrinter (hPrinter, 1, ("test of raw data", None, "RAW"))
# try:
# win32print.StartPagePrinter (hPrinter)
# win32print.WritePrinter (hPrinter, raw_data)
# win32print.EndPagePrinter (hPrinter)
# finally:
# win32print.EndDocPrinter (hPrinter)
# finally:
# win32print.ClosePrinter (hPrinter)
def on_created(self, event):
print("A file was created (", event.src_path, ")")
def on_deleted(self, event):
print("A file was deleted (", event.src_path, ")")
if __name__ == "__main__":
Flags=2
Name=None
Level=1
printers = win32print.EnumPrinters(Flags, Name, Level)
print("\nChoose a printer to use:")
i=1
for p in printers:
print(i,')' , p[2])
i = i+1
if sys.version_info >= (3,):
raw_data = bytes ("This is a test", "utf-8")
else:
raw_data = "This is a test"
printer = int(input())
printer_name = printers[printer-1][2] #win32print.GetDefaultPrinter ()
print("You chose ", printer_name, "\nI will now print from the specified file with this printer")
hPrinter = win32print.OpenPrinter (printer_name)
# root = Tk()
# root.filename = filedialog.askopenfilename(initialdir = "/Desktop",title = "Select file",filetypes = (("log files","*.log"),("all files","*.*")))
file_path = "some_file_path" # root.filename
file_directory = os.path.dirname(file_path)
# print (file_path)
print (file_directory)
observer = Observer()
event_handler = Handler(observer, file_path, file_directory)
observer.schedule(event_handler, path=file_directory, recursive=False)
observer.start()
observer.join()
any ideas would be appreciated
EDIT:
After some debugging I found out that Windows10 is changing the file modification time twice every time I save it.
The proof of concept code is this:
prev_modification_time = os.path.getmtime(file_path)
while True:
current_mod_time = os.path.getmtime(file_path)
if prev_modification_time != current_mod_time :
print ("the file was modified, last modification time is: ", current_mod_time)
prev_modification_time = current_mod_time
pass
Final edit:
After testing my code on linux (Debian Stretch to be exact) it worked like a charm. So this combined with the previous edit probably shows that watchdog works fine and it is windows10 that has some issue. Should I post it on a different question or here?

Been trying to overlap these two images but I keep getting a TypeError: 'NoneType' object is not callable

I have been trying to get this work for a very long time but I couldn't seem to get it to work. I tried to import Image as well but canopy couldn't name the module Image. I really need some help with this one. Someone help me please, I'm so stuck right now.
import PIL
import matplotlib.pyplot as plt
import os.path
import PIL.ImageDraw
def get_images(directory=None):
if directory == None:
directory = os.getcwd() # Use working directory if unspecified
image_list = [] # Initialize aggregaotrs
file_list = []
directory_list = os.listdir(directory) # Get list of files
for entry in directory_list:
absolute_filename = os.path.join(directory, entry)
try:
image = PIL.Image.open(absolute_filename)
file_list += [entry]
image_list += [image]
except IOError:
pass # do nothing with errors tying to open non-images
return image_list, file_list
def ben(x_range=None):
background = PIL.Image.open("funland.jpg")
overlay = PIL.Image.open("shivam2.jpg")
background = background.convert("RGBA")
overlay = overlay.convert("RGBA")
background_pixels = background.load()
overlay_pixels = overlay.load()
if x_range == None:
for y in x_range(overlay.size[1]):
for x in x_range(overlay.size[0]):
background_pixels[x,y] = (background_pixels[x,y][0], background_pixels[x,y][1], background_pixels[x,y][2], 255)
if x_range == None:
for y in x_range(overlay.size[1]):
for x in x_range(overlay.size[0]):
overlay_pixels[x,y] = (overlay_pixels[x,y][0], overlay_pixels[x,y][1], overlay_pixels[x,y][2], 128)
new_img = PIL.Image.blend(background, overlay, 0.5)
new_img.save("new.png","PNG")
The error is in these two lines:
if x_range == None:
for y in x_range(overlay.size[1]):
First, you check if the range is a None object, then you try to call it with (overlay.size[1]). I guess you meant x_range != None?

How to hand over a dataframe between tkinter buttons?

I'm pretty new with python programming and this is my first question asked, so be gentle with me. Right now i am working on a tkinter GUI that reads CSV files, turns them into dataframes to edit them and save the processed file to a result.csv in a datapath. My Problem is that i want to read in the CSV with a function OpenFile() connected to one button and then use the returned dataframe in my "Editfunctions" that each also is connected to a button. That doesnt seem to work with my callback in the code. Here is what my tkinter GUI currently Looks like:
root = tk.Tk()
openbutton = tk.Button (root, text='OpenFile', command = lambda: OpenFile())
openbutton.pack()
brakebutton = tk.Button (root, text = 'EditFile', command = lambda: EditFile(z))
brakebutton.pack()
savenewbutton = tk.Button(root, text = 'SavetoNewFile', command = lambda: SaveinNewFile(out_tup_end3))
savenewbutton.pack()
saveexcbutton = tk.Button(root, text = 'AppendtoExistingFile', command = lambda: SavetoexistingFile(out_tup_end3))
saveexcbutton.pack()
root.mainloop()
MY functions essentially look like this:
def OpenFile():
name = askopenfilename()
df = pd.read_csv(name, sep = ';')
return df
def EditFile(z):
df1 = z[[]]
.
.
.
.
return out_tup_end3
def SaveinNewFile(out_tup_end3):
out_tup_end3.to_csv("datapath", sep = ';', index = 0, mode = 'w')
def SavetoexistingFile(out_tup_end3):
with open("datapath", 'a') as f:
out_tup_end3.to_csv(f, header=False, sep = ';', index = 0)
def main():
z = OpenFile()
EditFile(z)
editedFile = EditFile(z)
SaveinNewFile(editedFile)
SavetoexistingFile(editedFile)
if __name__ == "__main__":
main()
So I think the not properly working part is that the callback is not handing over the dataFrame read from OpenFile() to EditFile(z). How can i achieve that?
Thanks for the help in advance!!
command= executes function but it doesn't care of value returned from this function so you have to use global variables to use result from one function in other function.
You code could look like this
#!/usr/bin/env python3
import tkinter as tk
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showinfo, showwarning
import pandas as pd
# --- functions ---
def open_file():
# inform function to use global variables
global df
name = askopenfilename()
if name:
df = pd.read_csv(name, sep=';')
showinfo("INFO", "DataFrame created")
def edit_file():
# inform function to use global variables
global df, out_tup_end3
if df is None:
#print("Read file first")
showwarning("WARNING", "Read file first")
else:
df1 = df[[]]
# ...
out_tup_end3 = df1
showinfo("INFO", "DataFrame edited")
def save_in_new_file():
# inform function to use global variables
global out_tup_end3
if out_tup_end3 is None:
#print("Read file first")
showwarning("WARNING", "Read file first")
else:
out_tup_end3.to_csv("datapath", sep=';', index=0, mode='w')
showinfo("INFO", "DataFrame saved")
def save_to_existing_file():
# inform function to use global variables
global out_tup_end3
if out_tup_end3 is None:
#print("Read file first")
showwarning("WARNING", "Read file first")
else:
with open("datapath", 'a') as f:
out_tup_end3.to_csv(f, header=False, sep=';', index=0)
showinfo("INFO", "DataFrame appended")
# --- main ---
if __name__ == "__main__":
# create global variables
df = None
out_tup_end3 = None
# GUI
root = tk.Tk()
b = tk.Button(root, text='Open File', command=open_file)
b.pack(fill='x')
b = tk.Button(root, text='Edit File', command=edit_file)
b.pack(fill='x')
b = tk.Button(root, text='Save to New File', command=save_in_new_file)
b.pack(fill='x')
b = tk.Button(root, text='Append to Existing File', command=save_to_existing_file)
b.pack(fill='x')
root.mainloop()
Or learn how to use classes and self. instead of global

Resources