How do I write to the file I selected using filedialog.asksaveasfile? - python

I am trying to write to a file that I just created using the filedialog.asksaveasfile. I set the mode to 'w'. Do I have to open the file again or something?
f = filedialog.asksaveasfile(mode='w', defaultextension=".csv")
keyList = []
for n in aDict.keys():
keyList.append(n)
keyList = sorted(keyList, key=operator.itemgetter(0,1))
csvWriter = csv.writer(f)
for key in keyList:
sal1 = aDict[(key[0],key[1])][0]
sal2 = aDict[(key[0],key[1])][1]
csvWriter.writerow(key[0], key[1], sal1, sal2)
f.close()

You can simply use the write function of the reference (of type _io.TextIOWrapper) returned by the asksaveasfile function.
For example
from tkinter import filedialog, Tk
root = Tk().withdraw()
file = filedialog.asksaveasfile(mode='w', defaultextension=".csv")
if file:
file.write("Hello World")
file.close()
Note that the object returned by the asksaveasfile function is of the same type or class of the object returned by the built-in open function. Note also that the same function returns None, if Cancel is pressed when the dialog pops up.

Related

Trying to add an incrementing number to all instances of a pattern in a text file

I'm a complete beginner, started today kind but I did a little C++ a few years ago, I'm trying to write a code that will read a text file and add a number to the start of each pattern that increments as it reads further.
So far I've written:
import tkinter as tk
import re
master = tk.Tk()
from tkinter.filedialog import askopenfilename
filename = askopenfilename()
file = open(filename, "r+")
filetext = file.read()
pattern = '"name":"(.*?)"'
name = re.findall(pattern, filetext)
print (name)
namereplace = re.sub(pattern, "test", filetext)
print ("this ran")
file.close()
Which opens a prompt to select a text file, reads the text file and finds all the strings I need to add the order to, but it does not replace them with "test".
First, to have your replacement in the file, you need to actually write the result back to the file.
To do this, you have two options (cmp. Replace and overwrite instead of appending):
Just open the file again in w mode after reading it and write the output of your replacement to it:
import tkinter as tk
import re
master = tk.Tk()
from tkinter.filedialog import askopenfilename
filename = askopenfilename()
pattern = '"name":"(.*?)"'
with open(filename, "r") as infile:
filetext = infile.read()
infile.close()
with open(filename, "w") as outfile:
outfile.write(re.sub(pattern, "test", filetext))
outfile.close()
Use seek to move the beginning of the file and truncate to inplace replace:
import tkinter as tk
import re
master = tk.Tk()
from tkinter.filedialog import askopenfilename
filename = askopenfilename()
pattern = '"name":"(.*?)"'
with open(filename, "r+") as infile:
filetext = infile.read()
infile.seek(0)
infile.write(re.sub(pattern, "test", filetext))
infile.truncate()
infile.close()
Second, concerning the main part of your question, the replacement by an incrementing number: I don't think you can do this with a single call of re.sub().
What you could do is read the file line by line and linewise substitute a counter variable. Whenever you successfully match, you increment your counter afterwards. To determine this, you could e.g. use re.subn() which will not only return the new string but also the number of substitutions.
Full example:
import tkinter as tk
import re
master = tk.Tk()
from tkinter.filedialog import askopenfilename
filename = askopenfilename()
pattern = '"name":"(.*?)"'
with open(filename, "r") as infile:
filetext = ""
count = 1
line = infile.readline()
while line:
matchtuple = re.subn(pattern, str(count), line)
if matchtuple[1]:
count += 1
filetext += matchtuple[0]
line = infile.readline()
infile.close()
with open(filename, "w") as outfile:
outfile.write(filetext)
outfile.close()
Input:
"bla":"bal"
"name":"baba"
"blah":"blah"
"name":"keke"
Output:
"bla":"bal"
1
"blah":"blah"
2

Python script need to save output to text file

I have peiced together some code from the internet to capture pressed keys and the current active window title and am trying to write the output of the python script to a text file.
The script works fine in the IDLE console and prints pressed keys and logs any change in the current active window.
from pynput.keyboard import Key, Listener
import time
from win32gui import GetWindowText, GetForegroundWindow
import datetime
from threading import Thread
def on_press(key):
print ('{0} pressed'.format(key))
def on_release(key):
('{0} release'.format(key))
if key == Key.esc:
return False
def get_titles():
current_title = None
while True:
moment2 = datetime.datetime.now().strftime("%d-%b-%Y [ %H:%M:%S ]")
new_title = GetWindowText(GetForegroundWindow())
if new_title != current_title:
if len(new_title) > 0:
#logging.info(" Moved to : " + new_title)
current_title = new_title
time.sleep(0.1)
#print(new_title)
ff= (moment2 + " : " + "Moved T0 : "+ new_title)
print (ff)
I am looking for a simple way to write the outputs i can see in the console to a text file. It is probably very simple but i am very much a beginner. Thanks
Python has a native open() function, no import needed, which allows you to handle files. This function "loads" the file into memory, and can be set into various modes:
open("filename.txt", "a"), appending the content to a new line;
open("filename.txt", "w"), overwriting the content; and
open("filename.txt", "r"), setting it to read-only.
open("filename.txt", "x"), to create a file.
You can add a "+" to each of this modes ("a+", "w+"), if you want the file to be created if it doesn't already exist.
You define the file in memory to a variable as such: a = open("filename.txt", "w"), and can then text = a.read() to load the content of the file to a string, or a.readlines() to load the strings into an array, split per \n.
Use a.write("Your desired output") to save the content to the file, if the file is in write or append modus.
Edit:
Try to only open files for as long as they are actually needed.
with open("filename.txt", "r") as f:
file_contents = f.read()
# file_contents = "This file contains\nvery important information"
file_lines = f.readlines()
# file_lines = ["This file contains", "very important information"]
# Similar to file_lines = file_contents.split("\n")
in order to avoid blocking other parts of your program, and avoid corrupting your files if Python crashes unexpectedly.
Just add
with open('textfile.txt', 'a+') as f:
f.write(ff)
a option is for appending to a file and + means that if the file is not there just create one with the specified name.
EDIT:
def on_press(key):
print ('{0} pressed'.format(key))
with open('textfile.txt', 'a+') as f:
f.write(ff)
EDIT 2:
def on_press(key):
print ('{0} pressed'.format(key))
k = key + '\n'
with open('textfile.txt', 'a+') as f:
f.write(key)
# and in get_titles()
ff= (moment2 + " : " + "Moved T0 : "+ new_title + '\n')
with open('textfile.txt', 'a+') as f:
f.write(ff)
try this when run program in console
python your_script.py > path_to_output_file/outpot.txt
in case '>' not work then try '>>'

Sorted function in python writing to a file

The task:
Your program should read from the file, storing the names and
corresponding email addresses in a dictionary as key-value pairs.
Then, the program should display a menu that lets the user enter the
numbers 1 through 5, each corresponding to a different menu item:
When the user enters 5, the program should write the names and email
addresses in alphabetical order by first name to the file
phonebook.out You can use the sorted() function which accepts a
dictionary argument to sort a dictionary based on Key
This is my code:
def write_to_file(contact):
file = open("phonebook.out", "w")
contactsort = dict(sorted(contact.items()))
phonebook.write(contact)
phonebook.close
However, this code isn't working. I'm not sure why, so any help is appreciated. thank you.
Have you tried json file?
Like this:
import json
filename = "phonebook.json"
def write_to_file(contact):
with open(filename, 'w') as f_obj:
contactsort = dict(sorted(contact.items()))
json.dump(contact, f_obj)
This is your code:
def write_to_file(contact):
file = open("phonebook.out", "w")
contactsort = dict(sorted(contact.items()))
phonebook.write(contact)
phonebook.close
As #Cheche mentioned, you are declaring the output as file but using it as phonebook. Simply replace file = open("phonebook.out", "w") with phonebook = open("phonebook.out", "w"). Also, you are storing the sorted names to contactsort but writing contact to the file. As a side note, phonebook.close needs to be be phonebook.close() with the parentheses to call the function.
The way you sort the dict is incorrect. Try:
contactsort = {key: contact[key] for key in sorted(contact.iterkeys())}
Also, you should try to use with when possible. with takes care of closing the file for you. Final code:
def write_to_file(contact):
with open("phonebook.out", "w") as phonebook:
contactsort = {key: contact[key] for key in sorted(contact.iterkeys())}
phonebook.write(str(contactsort))
def write_to_file(contact):
phonebook = open("phonebook.out", "w")
contactsort = dict(sorted(contact.items()))
phonebook.write(str(contactsort))
phonebook.close()
write_to_file({"name":9090909090, "name_a":8080808080})
here You go

How to write a dictionary to a .py file?

I have a dictionary in "albums_data.py" and "album.py" as main program.
I need to update the add_one() function in main program to write the actual state of dictionary in to "albums_data.py" and save it after some data is added to dictionary (using the add_one() function).
Here is the source code:
albums_data.py
albums= {}
albums["Adele"]="21"
albums["Michael Jackson"]="Thriler"
albums["Lady Gaga"]="The Fame"
album.py
import tkinter
from albums_data import *
root=tkinter.Tk()
root.title("DICT example")
#Functions
def show_all():
#clear the listbox
lb_music.delete(0,"end")
#iterate throught the keys and add to the listbox
for artist in albums:
lb_music.insert("end",artist)
def show_one():
artist=lb_music.get("active") #active is clicked field
album=albums[artist]
msg=artist+" - "+album
lbl_output["text"]=msg #Ready is replaced with msg
def add_one():
info=txt_input.get()
split_info=info.split(",") #list is created after is separated with ","
artist=split_info[0]
album=split_info[1]
albums[artist]=album
show_all()
txt_input.delete(0,"end")
#write to .py file (not worked to txt also) ->permission denied
f = open("albums_data.py","w")
f.write( str(albums) )
f.close()
#GUI
lbl_output=tkinter.Label(root,text="Ready")
lbl_output.pack()
txt_input=tkinter.Entry(root)
txt_input.pack()
lb_music=tkinter.Listbox(root)
lb_music.pack()
btn_show_all=tkinter.Button(root,text="Show all",command=show_all)
btn_show_all.pack()
btn_show_one=tkinter.Button(root,text="Show one",command=show_one)
btn_show_one.pack()
btn_add_one=tkinter.Button(root,text="Add one",command=add_one)
btn_add_one.pack()
root.mainloop()
Use JSON.
import json
d = { "hello": "world" }
with open('state.json', 'w') as f:
json.dump(d, f)
with open('state.json', 'r') as f:
d2 = json.load(f)
assert d == d2

How can I use askopenfile to get a valid filename

I'm trying to create a program with Tkinter and tkFileDialog that opens a file for reading and then packs it into a text widget but, whenever I run this:
from Tkinter import *
from tkFileDialog import askopenfile
import time
m = Tk()
def filefind():
file = askopenfile()
f = open(str(file), "r+")
x = f.read()
t = Text(m)
t.insert(INSERT, x)
t.pack()
b = Button(m, text='File Picker', command=filefind)
b.pack()
m.mainloop()
I get this:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
return self.func(*args)
File "C:\Users\super\PycharmProjects\untitled1\File Picker.py", line in filefind
f = open(str(file), "r+")
IOError: [Errno 22] invalid mode ('r+') or filename: "<open file u'C:/Users/super/PycharmProjects/untitled1/util.h', mode 'r' at 0x00000000026E0390>"
Here is the issue; askopenfile() is returning an object, not just the name. If you print file, you will get <_io.TextIOWrapper name='/File/Path/To/File.txt' mode='r' encoding='UTF-8'>. You want the name= from the object. To get that, all you need to do is replace f = open(str(file), "r+") with f = open(file.name, "r+").
Here is how it will look in your code:
from Tkinter import *
from tkFileDialog import askopenfile
import time
m = Tk()
def filefind():
file = askopenfile()
f = open(file.name, "r+") # This will fix the issue.
x = f.read()
t = Text(m)
t.insert(INSERT, x)
t.pack()
b = Button(m, text='File Picker', command=filefind)
b.pack()
m.mainloop()
Edit
A cleaner way of doing this is by letting askopenfile() do the work of opening a file instead of 're-opening' it again with open(). Here is the cleaner version:
file = askopenfile()
x = file.read()

Categories