I would like to have my tkinter program prompt the user to select the path the want to save the file which will be produced by the program.
My code looks like this. At this stage the program only saves to one file (the one I defined to test the program)
What code would I use to have 'test_write.csv' changed to any file the user chooses?
##Writing to .cvs file
with open('test_write.csv', 'w') as fp:
a = csv.writer(fp)
# write row of header names
a.writerow(n)
Thank you
Here's an example using tkFileDialog:
import Tkinter
import tkFileDialog
import csv
formats = [('Comma Separated values', '*.csv'), ]
root = Tkinter.Tk()
file_name = tkFileDialog.asksaveasfilename(parent=root, filetypes=formats, title="Save as...")
if file_name:
with open(file_name, 'w') as fp:
a = csv.writer(fp)
# write row of header names
a.writerow(n)
Use the tkFileDialog module.
Example:
import tkFileDialog
with open(tkFileDialog.asksaveasfilename(), "w") as fp:
...
Solution for python3.xxx
import tkinter
from tkinter.filedialog import asksaveasfilename
with open(asksaveasfilename(), 'w') as fp:
Related
I am trying to write a list to a csv file.
the following code runs and returns no error, but it doesnt work, in that it doesnt actually populate the csv file with the stuff in the list. I am probably doing it wrong because I don't understand something.
import newspaper
import os
from newspaper import article
libya_newspaperlist = []
libya_newspaper=newspaper.build('https://www.cnn.com', memoize_article=False)
for article in libya_newspaper.articles:
libya_newspaperlist.append(article.url)
import csv
os.chdir("/users/patrickharned/")
libya_newspaper.csv = "/users/patrickharned/libya_newspaper.csv"
def write_list_to_file(libya_newspaperlist):
"""Write the list to csv file."""
with open("/users/patrickharned/libya_newspaper.csv") as outfile:
outfile.write(libya_newspaperlist)
So I changed the code to this.
import newspaper
import os
from newspaper import article
libya_newspaperlist = []
libya_newspaper=newspaper.build('https://www.cnn.com', memoize_article=False)
for article in libya_newspaper.articles:
libya_newspaperlist.append(article.url)
import csv
os.chdir("/users/patrickharned/")
libya_newspaper.csv = "/users/patrickharned/libya_newspaper.csv"
with open("/users/patrickharned/libya_newspaper.csv", "w") as outfile:
outfile.write(str(libya_newspaperlist))
now it does output to the csv file, but it only outputs the first entry and wont do the rest. any suggestions?
You have to open the file in write mode:
with open("/users/patrickharned/libya_newspaper.csv", "w") as outfile:
outfile.write(libya_newspaperlist)
I have a file with strings that were pulled out of our HR system that are images of people that work for our company. I wrote the following code to convert these strings into .jpg files.
d is the name of the new file and x is the image string. I have printed both of these variables and they seem to be working. The file is saving and it is 71KB but when I open it in paint it says that it "cannot read this file and This is not a valid bitmap file, or its format is not currently supported."
I opened it with Photos and it just said it "can't open this file." Are you able to see any issue with the code?
import csv
import base64
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename()
with open(file_path, 'r') as csvfile:
readCSV = csv.reader(csvfile,delimiter=',')
next(readCSV)
for line in readCSV:
d = line[0]
x = line[1]
y = base64.encodebytes(x.encode())
with open("C:\\%s.jpg" %(d), "wb") as fh:
fh.write(base64.decodebytes(y))
fh.close()
break
from an GUI application designed with tkinter, I wish to save some datas in a file in appending mode. To get the file's name I use asksaveasfilename from filedialog module. Here is the code:
from tkinter.filedialog import asksaveasfilename
def save_file():
file_name = asksaveasfilename()
if file_name:
f = open(file_name, 'a')
contents = tab_chrono.text_area.get(1.0, 'end')
f.write(contents)
f.close()
The problem happens when I select in the dialog an existing file, I got a warning that the file will be overwritten. It is not true since I append in the file.
Is there a way to get rid of this warning ? Or do I have to rewrite a askappendfilename myself ? This is missing in filedialog module.
The asksaveasfilename dialog accepts a confirmoverwrite argument to enable or disable the file existence check.
file_name = asksaveasfilename(confirmoverwrite=False)
This can be found in the Tk manual for tk_getSaveFile but doesn't appear to be documented for tkinter. It was introduced in Tk 8.5.11 so is relatively new in Tk terms (released Nov 2011).
Use the option confirmoverwrite to prevent the message, when selecting an existing file.
import tkFileDialog
import time
class Example():
dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False)
fname = dlg
if fname != '':
try:
f = open(fname, "rw+")
text = f.read()
print text
except:
f = open(fname, "w")
new_text = time.time()
f.write(str(new_text)+'\n')
f.close()
Edit: Note that I am using f.read() to be able to print the existing text.
You may want to remove the f.read() and subsequent print statement and replace them with a f.seek(0,2) which positions the pointer at the end of the existing file.
The other option is as follows using the append option in the file open, which will create the file if it doesn't already exist:
import tkFileDialog
import time
class Example():
dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False)
fname = dlg
if fname != '':
f = open(fname, "a")
new_text = time.time()
f.write(str(new_text)+'\n')
f.close()
long time lurker, but never posted here. Sorry if this isn't a good post...I made a program that uses regex to pull the names and emails out of resumes. I can get it to open a specific file in my resume folder, but getting the program to iterate over all of the files in the folder has me stumped. Here's the pseudo-code for what I'm doing:
open resume folder
read file1.txt
execute nameFinder
execute emailFinder
create new dictionary candidateData
Export to Excel
read file2.txt
...
Here's the code:
import re
import os
import pprint
with open('John Doe -Resume.txt', 'r') as f:
#This pulls the first line of the resume,
#Which is generally the name.
first_line_name = f.readline().strip()
#This pulls the Email from the resume.
bulkemails = f.read()
r = re.compile(r'(\b[\w.]+#+[\w.]+.+[\w.]\b)')
candidateEmail = r.findall(bulkemails)
emails = ""
for x in candidateEmail:
emails += str(x)+"\n"
#This creates the dictionary data
candidateData = {'candidateEmail' : str(candidateEmail), \
'candidateName' : str(first_line_name)}
pprint.pprint(candidateData)
Then, I get this as an output:
{'candidateEmail': "['JohnDoe#gmail.com']",
'candidateName': 'John Doe'}
All ready to be exported into Excel.
SO HERE"S MY QUESTION FOR YOU! How do I get it to do this for ALL of the .txt files in my resume folder, and not just the file I specify? Also, any cod critique would be greatly appreciated, Thanks guys! :D
You can use glob to iterate over all .txt files in your directory and then run the function on each file. Add this to the start
import re
import os
import glob
import pprint
os.chdir("resumes")
for file in glob.glob("*.txt"):
with open(file, 'r') as f:
#Rest of your execution code here
EDIT: In answer to your question in the comments:
import re
import os
import glob
import pprint
candidateDataList = []
for file in glob.glob("*.txt"):
with open(file, 'r') as f:
#This pulls the first line of the resume,
#Which is generally the name.
first_line_name = f.readline().strip()
#This pulls the Email from the resume.
bulkemails = f.read()
r = re.compile(r'(\b[\w.]+#+[\w.]+.+[\w.]\b)')
candidateDataList.append({'name':str(first_line_name),
'email':r.findall(bulkemails)})
pprint.pprint(candidateDataList)
#Jakob's answer is spot on. I only wanted to mention a nice alternative which I usually prefer myself, the pathlib:
import re
import pprint
from pathlib import Path
resumes_dir = Path("resumes")
for path in resumes_dir.glob("*.txt"):
with path.open() as f:
#Rest of your execution code here
I have a Python script which modifies a CSV file to add the filename as the last column:
import sys
import glob
for filename in glob.glob(sys.argv[1]):
file = open(filename)
data = [line.rstrip() + "," + filename for line in file]
file.close()
file = open(filename, "w")
file.write("\n".join(data))
file.close()
Unfortunately, it also adds the filename to the header (first) row of the file. I would like the string "ID" added to the header instead. Can anybody suggest how I could do this?
Have a look at the official csv module.
Here are a few minor notes on your current code:
It's a bad idea to use file as a variable name, since that shadows the built-in type.
You can close the file objects automatically by using the with syntax.
Don't you want to add an extra column in the header line, called something like Filename, rather than just omitting a column in the first row?
If your filenames have commas (or, less probably, newlines) in them, you'll need to make sure that the filename is quoted - just appending it won't do.
That last consideration would incline me to use the csv module instead, which will deal with the quoting and unquoting for you. For example, you could try something like the following code:
import glob
import csv
import sys
for filename in glob.glob(sys.argv[1]):
data = []
with open(filename) as finput:
for i, row in enumerate(csv.reader(finput)):
to_append = "Filename" if i == 0 else filename
data.append(row+[to_append])
with open(filename,'wb') as foutput:
writer = csv.writer(foutput)
for row in data:
writer.writerow(row)
That may quote the data slightly differently from your input file, so you might want to play with the quoting options for csv.reader and csv.writer described in the documentation for the csv module.
As a further point, you might have good reasons for taking a glob as a parameter rather than just the files on the command line, but it's a bit surprising - you'll have to call your script as ./whatever.py '*.csv' rather than just ./whatever.py *.csv. Instead, you could just do:
for filename in sys.argv[1:]:
... and let the shell expand your glob before the script knows anything about it.
One last thing - the current approach you're taking is slightly dangerous, in that if anything fails when writing back to the same filename, you'll lose data. The standard way of avoiding this is to instead write to a temporary file, and, if that was successful, rename the temporary file over the original. So, you might rewrite the whole thing as:
import csv
import sys
import tempfile
import shutil
for filename in sys.argv[1:]:
tmp = tempfile.NamedTemporaryFile(delete=False)
with open(filename) as finput:
with open(tmp.name,'wb') as ftmp:
writer = csv.writer(ftmp)
for i, row in enumerate(csv.reader(finput)):
to_append = "Filename" if i == 0 else filename
writer.writerow(row+[to_append])
shutil.move(tmp.name,filename)
You can try:
data = [file.readline().rstrip() + ",id"]
data += [line.rstrip() + "," + filename for line in file]
You can try changing your code, but using the csv module is recommended. This should give you the result you want:
import sys
import glob
import csv
filename = glob.glob(sys.argv[1])[0]
yourfile = csv.reader(open(filename, 'rw'))
csv_output=[]
for row in yourfile:
if len(csv_output) != 0: # skip the header
row.append(filename)
csv_output.append(row)
yourfile = csv.writer(open(filename,'w'),delimiter=',')
yourfile.writerows(csv_output)
Use the CSV module that comes with Python.
import csv
import sys
def process_file(filename):
# Read the contents of the file into a list of lines.
f = open(filename, 'r')
contents = f.readlines()
f.close()
# Use a CSV reader to parse the contents.
reader = csv.reader(contents)
# Open the output and create a CSV writer for it.
f = open(filename, 'wb')
writer = csv.writer(f)
# Process the header.
header = reader.next()
header.append('ID')
writer.writerow(header)
# Process each row of the body.
for row in reader:
row.append(filename)
writer.writerow(row)
# Close the file and we're done.
f.close()
# Run the function on all command-line arguments. Note that this does no
# checking for things such as file existence or permissions.
map(process_file, sys.argv[1:])
You can run this as follows:
blair#blair-eeepc:~$ python csv_add_filename.py file1.csv file2.csv
you can use fileinput to do in place editing
import sys
import glob
import fileinput
for filename in glob.glob(sys.argv[1]):
for line in fileinput.FileInput(filename,inplace=1) :
if fileinput.lineno()==1:
print line.rstrip() + " ID"
else
print line.rstrip() + "," + filename