I have created a program that can edit the contents of a text file. Assume that my program looks something like this:
from tkinter import *
from tkinter import filedialog
root = Tk()
def open_file():
file_to_open = filedialog.askopenfilename(initialdir="C:/" , filetypes=(("All files" , "*.*"),))
if file_to_open != "":
file = open(file_to_open , 'r')
content_in_file = file.read()
file.close()
text.delete('1.0' , END)
text.insert('1.0' , content_in_file)
def save_file():
path = filedialog.asksaveasfilename(initialdir="C:/" , filetypes=(("All files" , ""),))
if path != "":
file = open(path , 'w')
file.write(text.get('1.0' , 'end-1c'))
file.close()
text = Text(root , width = 65 , height = 20 , font = "consolas 14")
text.pack()
open_button = Button(root , text = "Open" , command = open_file)
open_button.pack()
save_button = Button(root , text = "Save" , command = save_file)
save_button.pack(pady=20)
mainloop()
The problem here is that when I click on a text file in my file explorer, it opens with the default windows notepad instead of opening with my program.
What I want is that all the text files should open with my program instead of opening with the default windows Notepad.
Here's what I did (in order):
After completing the following steps, I tried opening my text file, but it says:
I tried converting my python program into an exe file (using pyinstaller) and then following the steps above, but when I open the text file I get an other error:
Is there anything wrong with my code or the steps I followed?
I would really appreciate it if anyone could guide me through how I can open a text file with my program.
The code looks fine, it just needed to take the argument, when you open-with you are calling some executable on a path o multiple paths, the first argument is de executable itself, so if the code is executed with more than 1 argument it's a path; the problem with this is that the command is python and not file.py, a fix would be convert it to a exe or call it with a bat.
This example may look different but is more or less the same, just packed inside a class.
from tkinter import filedialog
import tkinter as tk
import sys
import os
SRC_PATH = os.path.dirname(__file__)
class File_Editor(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.text = tk.Text(self, width=65, height=20, font="consolas 14")
self.text.pack()
self.open_button = tk.Button(self, text="Open", command=self.open_file)
self.open_button.pack()
self.save_button = tk.Button(self, text="Save", command=self.save_file)
self.save_button.pack(pady=20)
def open_file(self, file=None):
path = file or filedialog.askopenfilename(
initialdir=SRC_PATH, filetypes=(("All files", "*.*"),))
if os.path.exists(path) and os.path.isfile(path):
with open(path, 'r', encoding='utf-8') as file:
content_in_file = file.read()
self.text.delete('1.0', tk.END)
self.text.insert('1.0', content_in_file)
def save_file(self):
path = filedialog.asksaveasfilename(initialdir=SRC_PATH, filetypes=(("All files", ""),))
if os.path.exists(path) and os.path.isfile(path):
with open(path, 'r', encoding='utf-8') as file:
file.write(self.text.get('1.0', 'end-1c'))
if __name__ == '__main__':
app = File_Editor()
if len(sys.argv) > 1:
app.open_file(sys.argv[1])
app.mainloop()
This .bat file is just passing the firs argument to the file; a full path is required to execute, it will not be called in a directory you expect.
#echo off
python D:\Escritorio\tmp_py\temp_3.py %1
Now you just call the open-with File_Editor.bat
Related
It is possible to open a file in tkinter from pc using right click->Open with->My Program.
I just want the file path when using this method.
You can't open a file using the method you are asking for( right-click > Open with > My Program) but you can create a program to open and edit files within a GUI using the Tkinter file dialog library and the open() function.
An example of the Method I am talking about:
from tkinter import *
from tkinter.filedialog import askopenfilename
windows = Tk()
windows.title("File Dialog Example")
windows.geometry("500x500")
def file_open():
text_window.delete('1.0', END)
filePath = askopenfilename(
initialdir='C:/', title='Select a File', filetype=(("Text File", ".txt"), ("All Files", "*.*")))
with open(filePath, 'r+') as askedFile:
fileContents = askedFile.read()
text_window.insert(INSERT, fileContents)
print(filePath)
open_button = Button(windows, text="Open File", command=file_open).grid(row=4, column=3)
text_window = Text(windows, bg="white",width=200, height=150)
text_window.place(x=50, y=50)
windows.mainloop()
And in order to save the changes to the file, you can read the contents in the Text Box and then write the contents to the Opened file.
Thanks
I have just started with Tkinter, so please do not judge me on this... I want to get the path to the csv file and then use it without terminating the program. The following code works, however, I exit the program:
from tkinter import *
from tkinter import filedialog
root = Tk()
root.title('ask and print path to file')
def get_path():
global path
path = filedialog.askopenfile(title = 'Select the .csv file with keywords', filetypes = (('csv files','*.csv'), ('All files', '*.*')))
path_button = Button(root, text = 'Select keywords', command = get_path)
path_button.pack()
button_quit = Button(root, text ='Exit', command = root.quit)
button_quit.pack(side = BOTTOM)
root.mainloop()
print(path.name)
The print statement here is just for simplicity (in reality I want to use pd.read_csv(path.name) to read the file, make some wrangling an then return changed file).
How to make the print(path.name) without exiting GUI on the background?
I would change the button command to a function which does all of the file code:
# update the button to call a different function
path_button = Button(root, text = 'Select keywords', command = handle_file)
# make a new function to handle everything
def handle_file():
path = get_path()
pd.read_csv(path.name)
# any other stuff
# change this function too, so that it returns a value to "handle_file* rather than setting a global variable
def get_path():
return filedialog.askopenfile(title = 'Select the .csv file with keywords', filetypes = (('csv files','*.csv'), ('All files', '*.*')))
This way you dont use global variables, and your code can perform stuff after you get the file. The essence of this is that you perform your processing code (pd.read_csv()) at the same time you get the path.
I want to read the content of the selected file by opening with tk filedialog. When i select the file and click on open button the file doesn't open but rather close the dialog box .How can i open the selected file with notepad so i can be able to read the content in the file.
from tkinter import *
from tkinter import filedialog
def my_file():
filename = filedialog.askopenfile(mode="r", initialdir="/", title="select file",
filetypes=(("text files", "*.txt"), ("all files", "*.*")))
root = Tk()
root.geometry("300x300")
#open the selected txt file with notepad to read the content
b = Button(root, text="open text file", command = my_file).pack()
root.mainloop()
EDIT
With hint from #PM 2RING and #Erik i changed the filedialog.askopenfile to filedialog.askopenfilename to return it to open with notepad.exe when i select the file.
THis is the code:
from tkinter import *
from tkinter import filedialog
import os
def my_file():
filename = filedialog.askopenfilename( initialdir="C:/", title="select
file", filetypes=(("text files", "*.txt"), ("all files", "*.*")))
for f in filename:
return f
os.system(r"C:/notepad.exe" + f)
root = Tk()
root.geometry("300x300")
#open the selected txt file with notepad to read
the content
b = Button(root, text="open text file", command = my_file).pack()
root.mainloop()
it output this error :
Blockquote'C:/notepad.exet' is not recognized as an internal or external command,
operable program or batch file.
Blockquote
but when i changed the return to print it print the directory to terminal.I tried to open with subprocess
subprocess.Popen([r'C:\Program Files (x86)\Notepad.exe' + f])
it also doesn't open with this one to.
There's a few things which need to be amended here.
First of all, C:/notepad.exe is not the location of Notepad (At least not on any Windows machine with a default setup), you can simply use notepad.exe which should make it more compatible with systems that have moved Notepad to another location (citation needed).
Secondly, executing . . .
for f in filename:
return f
os.system(r"C:/notepad.exe" + f)
Doesn't do what you seem to think it does. What's actually happening here is that your program is loading the string into the loop, evaluating the first character (Probably "C") and then returning the string to the Button widget which doesn't receive any returned values. This then breaks your function, so it never actually reaches your declaration of os.system(r"C:/notepad.exe" + f).
You also need to include a space between the statement used to open Notepad notepad.exe and the actual file declaration f, otherwise you're running something like notepad.exeC:/text.txt which is going to throw an error at you.
What you should be doing is something like the below:
from tkinter import *
from tkinter import filedialog
import os
def my_file():
filename = filedialog.askopenfilename( initialdir="C:/", title="select file", filetypes=(("text files", "*.txt"), ("all files", "*.*")))
os.system(r"notepad.exe " + filename)
root = Tk()
root.geometry("300x300")
b = Button(root, text="open text file", command = my_file).pack()
root.mainloop()
I'd like to add that I have no clue why you're doing this, why not simply display the text in a Text widget? What you're doing here is adding one extra step for people to open files in Notepad, instead of opening file explorer, finding the file and then opening it they have to open your program, then open file explorer, then find the file and then open it. It's adding at least one extra click not to mention the load time of your program.
As mentioned by PM 2Ring, I would use the os.system function. As mentioned in its description, "os.system(command)" let's you execute the command as if you had written it in the command prompt, so os.system("Notepad c:/users/yourName/junk.txt) would open a file named junk.txt if it were at that location.
In other words, once you have the filename from your filedialog.askopenfilename call, do something like this:
import os
os.system("Notepad " + filename) # where filename is the string that filedialog.askopenfilename returns
The implementation into your code shouldn't be too bad, but if you need a more complete example, let let me know.
The following code will display a button and a text widget. The button will load in your file, and the text widget will display it. I assume this is what you had in mind?
from tkinter import *
from tkinter import filedialog
def my_file():
file = filedialog.askopenfile(mode="r", initialdir="/", title="select file",
filetypes=(("text files", "*.txt"), ("all files", "*.*")))
t.insert(END, file.read())
file.close()
root = Tk()
root.geometry("300x300")
#open the selected txt file with notepad to read the content
t = Text(root)
t.grid(row=0, column=0)
b = Button(root, text="open text file", command = my_file)
b.grid(row=1, column=0)
root.mainloop()
I want to use extensions list example : [".txt",".html",".css"] for save as option in file dialog popup window. when I use this method
file_opt = options = {}
options['defaultextension'] = '.txt',I can able to write any file with .txt as default extension without choose in save as option but I want to choose extensions for save as in file dialog popup window from using my extensions list.
I'm using Python 3.5 based Anaconda IDE
If you look at the documentation here you can see that you can pass in the filetypes keyword which specifies a list of tuples that have the name, and file extension respectively for the different types of filetypes you want to be able to save as.. So you can do something along the lines of:
import tkinter as tk
from tkinter import filedialog as fd
def save_file():
filename = fd.asksaveasfilename(defaultextension='.txt',
filetypes= [('Text','.txt'), ('HTML', '.html'), ('CSS', '.css')])
if filename:
print("User saved the filename with extension:", filename.split(".")[-1])
root = tk.Tk()
button = tk.Button(root, text='Save File', command=save_file)
button.pack()
root.mainloop()
Or if you really want to use a dictionary for this:
import tkinter as tk
from tkinter import filedialog as fd
SAVE_OPTS = {'defaultextension':'.txt',
'filetypes': [('Text','.txt'), ('HTML', '.html'), ('CSS', '.css')]}
def save_file():
filename = fd.asksaveasfilename(**SAVE_OPTS)
if filename:
print("User saved the filename with extension:", filename.split(".")[-1])
root = tk.Tk()
button = tk.Button(root, text='Save File', command=save_file)
button.pack()
root.mainloop()
SaveFileDialog sd = new SaveFileDialog();
sd.Filter = "Text File (*.txt)|*.txt|PNG File (*.txt)|*.png"|...;
if(sd.ShowDialog() == DialogResult.OK) {
richTextBox1.SaveFile(sd.FileName, RichTextBoxStreamType.PlainText);
}
Hi Everyone I am working on my final project and I am creating a directory snooper
So here is the bottomline of this script:
GUI with Tkinter that asks user for directory and prompts user to
save a cvs file to the space of their choosing. CSV will contain
filename,file extension and file size taken from the directory that
the user inputed.
My GUI has a text scroll box that should print the process of the
script and print when it is done,
My problems:
When saving CSV. It does not produce a CSV and I get this error
"ValueError: I/O operation on closed file".asksaveasfilename() is
not working
GUI text scroll box is not working and printing out the information
i need
How do I add headers to my CSV so that my CSV will have
filename,extension,size, and comment
Attached below is my script. Can anyone help me with this?
from Tkinter import Tk
from tkFileDialog import askdirectory
from array import *
import os
version = '1.0'
import os
import csv
from Tkinter import BOTH, LEFT, TOP, END, StringVar
from ttk import Frame, Entry, Button, Label
from ScrolledText import ScrolledText
from tkFileDialog import askdirectory
from tkFileDialog import asksaveasfilename
class FileWalkerWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.pack(expand=True, fill=BOTH)
self.master.title("Directory Snooper v" + version)
self.master.iconname("Directory Snooper")
self.dir = StringVar() # tkinter does not work with standard python variables
self.dir.set(os.getcwd()) # set to current working directory
description = "This program walks through a directories " \
+ "print out name of directory file path. " \
+ "prints out mumber of files in your in your directory. " \
+ "It list files and tests for corrupted zipfiles and " \
+ "creates a CSV file of the findings"
row1 = Frame(self)
Label(row1, text="Choose Directory:").pack(side=LEFT, pady=10)
self.dir_ent = Entry(row1, width=80, textvariable=self.dir)
self.dir_ent.pack(side=LEFT)
Button(row1, text="Browse", width=10, command=self.browse).pack(side=LEFT, padx=5)
row1.pack(side=TOP, ipadx=15)
row2 = Frame(self)
btn = Button(row2, text="Snoop", command=self.savefile, width=15)
btn.pack(side=LEFT, padx=5, pady=10)
row2.pack(side=TOP)
self.output = ScrolledText(self, height=15, state="normal",
padx=10, pady=10,
wrap='word')
self.output.insert(END, description)
self.output.pack(side=LEFT, fill=BOTH, expand=True, padx=5, pady=5)
self.bind('<Key-Return>', self.savefile) # bind enter press to walk
def browse(self):
dirpath = askdirectory(parent=self, title="Select Directory")
self.dir.set(dirpath)
def savefile (self):
self.output.delete(1.0, END)
name=asksaveasfilename()
with open(name,'w') as csvfile:
dirList = os.listdir(self.dir.get())
data = ((fname, str(os.path.getsize(self.dir.get() + "/" + fname)), str(os.path.splitext(fname)[1]),) for
fname in
dirList)
for entry in data:
create=csv.writer(csvfile)
create.writerow(','.join(entry) + '\n')
csvfile.close()
if __name__ == '__main__':
FileWalkerWindow().mainloop()
When saving CSV. It does not produce a CSV and I get this error
"ValueError: I/O operation on closed file"
You do close the file in your for loop:
for entry in data:
create=csv.writer(csvfile)
create.writerow(','.join(entry) + '\n')
csvfile.close()
Unindent it to close the file after the for loop. You should move the csv.writer() outside of the for loop as well (as mentioned in comments):
create=csv.writer(csvfile)
for entry in data:
create.writerow(','.join(entry) + '\n')
csvfile.close()
GUI text scroll box is not working and printing out the information i need
The question is when you want to display the information!
You can add a button to print the content of the chosen directory or print it automatically when the user selects a folder to browse.
To do the latter, you can edit you browse method, which should look like:
def browse(self):
dirpath = askdirectory(parent=self, title="Select Directory")
self.dir.set(dirpath)
self.output.insert(END, "\n" + "\n".join(os.listdir(dirpath)))
How do I add headers to my CSV so that my CSV will have
filename,extension,size, and comment
Just write a Python string containing your headers before writing actual values:
with open(name,'w') as csvfile:
csvfile.write("filename,extension,size,comment")
dirList = os.listdir(self.dir.get())
# some other stuff after...
Please note also that, while it is strongly discouraged by Python guidelines to use from module import * in general, the standard way to import Tkinter is from Tkinter import * :)