Python: Writing to a file and reading it back out - python

I am saving a dictionary of student names as keys and grades lists as values. I am attempting to write the values to a file. At the moment I am writing them as strings.
def save_records(students, filename):
#saves student records to a file
out_file = open(filename, "w")
for x in students.keys():
out_file.write(x + " " + str(students[x]) + "\n")
out_file.close()
After saving the file, I try to read it back. The pertinent part of the read out is below.
while True:
in_line = in_file.readline()
if not in_line:
break
#deletes line read in
in_line = in_line[:-1]
#initialize grades list
in_line = in_line.split()
name = in_line[0]
students[name] = map(int, in_line[1:])
The read out code works well for normal text files that are pre-formatted. The format of the textfile is: key (whitespace) values separated by whitespace "\n". I would like to know how to write in to a text file by combining string and list elements.

If you have control over writing the data, I would recommend using a well-established format, such as JSON or INI. This would allow you to make use of common libraries, such as the json or ConfigParser modules, respectively.

Would it not be easier to use something like pythons pickle which is for storing things like dicts
...and then pretty print output to a separate file?
It's hard to say without knowing how you plan on using this...

Since students[name] = map(int, in_line[1:]), i assume you want to print the items of the list student[x] with whitespaces inbetween.
You could use the str.join method
' '.join(map(str,students[x]))

You may want to consider using Comma Separated Value files (aka csv files) instead of plain text files, as these provide a more structured way to read and write your data. Once written, you can open them in a spreadsheet program like Excel to view and edit their contents.
Re-writing your functions to work with csv files, and assuming you are using Python 2.x, we get something like:
import csv
def save_records(students, filename):
# note that csv files are binary so on Windows you
# must write in 'wb' mode; also note the use of `with`
# which ensures the file is closed once the block is
# exited.
with open(filename, 'wb') as f:
# create a csv.writer object
csv_out = csv.writer(f)
for name, grades in students.iteritems():
# write a single data row to the file
csv_out.writerow([name]+grades)
def read_records(filename):
students = dict()
# note that we must use 'rb' to read in binary mode
with open(filename, 'rb') as f:
# create a csv.reader object
csv_in = csv.reader(f)
for line in csv_in:
# name will have type `str`
name = line[0]
grades = [int(x) for x in line[1:]]
# update the `students` dictionary
students[name] = grades
return students

Related

How to save contents of a list to a file?

I have some question about my code:
def entry_book():
book = ["autor", "ime", "godina", "ISNB", "zanr", "cena", "broj"]
print ("Podaci za knjigu:")
book[0] = input ("Autor: ")
book[1] = input ("Naslov: ")
book[2] = input ("Godina: ")
book[3] = input ("ISNB: ")
book[4] = input ("Zanr: ")
book[5] = input ("Cena: ")
book[6] = input ("Kolicina: ")
record= "{}|{}|{}|{}|{}|{}|{}".format (book[0], book[1], book[2], book[3],
book[4], book[5], book[6])
print (book)
print (record)
f = open('books.txt','w')
f.write (record)
f.close()
f = open("books.txt")
x = f.read()
f.close()
print (x)
record1 = record.split('|')
print (record1)
second_meni()
This is code to store information on books, which I want to access later (like at a library). However, every time I add/create a new book, the old one gets deleted. Can anyone help me rewrite the code so it can store the old data as well. Or please explain what is the correct way to do it?
You have to use
f = open('knjige.txt', 'a')
'w' recreates the file (so use it only for NEW files, or if you don't mind it will be overwritten, 'a' appends to a file.
See python open built-in function: difference between modes a, a+, w, w+, and r+?
Also some unrelated suggestions:
Use the add instead of indices, or even better: use a dictionary
Use English variable names/comments.
Use code to check if the file read/write is ok, what if the file cannot be
written because of access restrictions or too less space on the disk?
Use different functions for the input, writing and printing, it makes testing/maintainability/extension much easier.
I took the liberty of pythonizing your code a bit.
def unos_knjiga():
headers = ["Autor", "Naslov", "Godina", "ISNB", "Zanr", "Cena", "Kolicina"]
print("Podaci za knjigu:")
knjiga = [input("{}".format(obj + ': ')) for obj in headers] # see 1
zapis = '|'.join(knjiga) # see 2
print(knjiga)
print(zapis)
with open('knjige.txt', 'a') as f: # see 3
f.write(zapis + '\n')
# i guess this is for testing?
with open("knjige.txt", 'r') as f:
x = f.read()
print(x)
# and this too?
zapis1 = zapis.split('|')
print(zapis1)
# this is not mentioned anywhere
second_meni()
1) This is a list comprehension. It creates lists by looping through stuff. In this case we are looping through the header list and use its items to construct input statements. The provided input is stored in the list.
2) .join() method. It does what you explicitly did. Joins items from iterators using a string between them.
3) the with keyword. Manages files so that you do not have to. Unless there is a reason not to use it, use it. This was also where the real problem with your code was. You have to use the 'a' mode. 'a' is for append, 'w' is for write. In this context, write means delete everything that was there and write this new stuff. Also note that 'a' mode can also create files, you do not need to temporarily switch to 'w' for that ('r' does not; 'r' is for read).
Cheers!
I think there are two methods to do this:
FIRST
f = open('knjige.txt','w')
is the piece of code which is responsible for rewriting the existing data in your file.
Other option which python offers to append some new data to the existing data is to open a file for writing using append 'a' method. So you can replace your above statement with
f = open('knjige.txt','a')
It won't replace the file with new data you enter.
SECOND
Other option is to open your file in read method, f = open('knjige.txt','r') and copy the existing data to a variable ( variable=f.read('knjige.txt') ). You can also use pickle module and its functions dump and load if you need to maintain your datatype.
Now concatenate your new data to the values in 'variable' and again open the file in write method and write it back to it.
Your call to open the file, f = open('knjige.txt','w') opens the file, truncating the existing contents should it exist. If you open the file with a mode that appends contents, like a it should not delete previous lines. See https://docs.python.org/2/library/functions.html#open for more information on opening files for reading / writing.

How can I convert a string in a file back to a list in Python?

I'm writing a tournament creator for a game that lacks it, just for personal use. It's a good exercise for school... however, I've stumbled upon a problem while finishing up the program.
So after the participants for the tournament have been decided, I ask the user (myself, my cousin too at most, if he comes over) if he wants to save the current list of participants. If so, a list containing the participants gets written to a file:
fileWrite = open('Previous Participants', 'w')
fileWrite.write(str(participants2))
fileWrite.close()
however, this converts the list to a string, so if I want to read it out the next time the program is run... I have a string. Not a list and I need the list for the tournament creator itself (randomizing the fights, etc).
So... how do I get this string back as a list? The problem is, I can use split, I think, but I believe that participant names with spaces would then be a problem.
Currently the file has this string from last time:
['Cell', 'Lord Slug', 'Time Patroller', 'Gotenks', 'Omega Shenron', 'Nail', 'Time Breaker Bardock', 'Piccolo', 'Frieza', 'Mr. Satan', 'Beerus', 'Nappa', 'Raspberry', 'Goten', 'Vegito', 'Goku']
Participants like 'Lord slug' will cause a problem if I do:
ownCharacters = input('Do you wish to use the same participants as last time? ')
if ownCharacters == 'yes' or ownCharacters == 'Yes':
try:
fileRead = open('Previous Participants', 'r')
participants2 = fileRead.read()
participants2.split
except FileNotFoundError:
participants2 = participants2
Won't they?
BTW participants2 has already been filled in with random names when the program arrives at this point, so if the file does not exist it should continue using the random names.
One better way to do this is writing the names to the file one per line:
fileWrite.write('\n'.join(participants2))
Then you can retrieve the list of names via readlines:
participants2 = fileRead.readlines() # elements will will need to be stripped
But, the proper way of serializing data to files is to use a tested library like pickle or json:
import json
# import pickle
with open('file.json', 'w') as f:
json.dump(participants, f)
# pickle.dump(participants, f)
Then you can retrieve the list via:
with open('file.json', 'r') as f:
participants = json.load(f)
# participants = pickle.load(f)
Don't write the list as string. There are a number of ways that you could do this. The most common would be to either write each user on a different line of the file, or to use a csv (or some other kind of delimiter).
import csv
with open('file_name.csv', newline='') as fh:
writer = csv.writer(fh)
writer.writerow(participants2)
write list first via join:
file.write(','.join(list))
read it and use split to get list back:
data = file.read() #read data
list = data.split(',')#split data
for multiple list different levels of seperation may work

Python: Exporting text list to a text file

I am new to Python and I was wondering how to save this hashed password list (stored in variable passwords)
['73868cb1848a216984dca1b6b0ee37bc', '2de9210e9173ca4151bb220a2ded6cdb', '8c064f4067cf0c59c68ec281f5786cb2']
to a text file in the format:
73868cb1848a216984dca1b6b0ee37bc
2de9210e9173ca4151bb220a2ded6cdb
8c064f4067cf0c59c68ec281f5786cb2
currently I am able to save it to a text file however it saves as
['73868cb1848a216984dca1b6b0ee37bc', '2de9210e9173ca4151bb220a2ded6cdb', '8c064f4067cf0c59c68ec281f5786cb2']
current code to save file:
f = open( 'hash.txt', 'w' )
f.write(repr(passwords) + '\n' )
f.close()
Please help :) Thank you
Reason for wanting to save in text is so I can call that list in a new script to decrypt them however because it saves as a list (and imports as a list) it creates a list in a list and messes up my decryption script.
Edit: Thank you all for the great answers :) its a huge help!
You can save it like this:
with open('hash.txt', 'w') as f:
f.write('\n'.join(passwords))
This achieves what you waht to do. (You could avoid the with-statement)
Load it like this:
passwords = []
with open('hash.txt', 'r') as f:
passwords.extend(f.read().split('\n'))
To use Python 3, you would have to be careful to convert the bytes to str first...
Greets.
EDIT:
Sorry, it must be passwords.extend() - not passwords.append().
You should use readlines() to pass the text from the file into the list and use that list like so:
passwords = []
with open('hash.txt', 'r') as f:
passwords = f.readlines()
f.close()
If you come across '\n', then just use something like "".join(passwords)
You can use the following code :
f = open( 'hash.txt', 'w' )
for a in passowrds:
f.write(a + '\n' ) #you have to pass them as separate variables
f.close()
Whenever you have to take out take out values from a list, you can use the for loop Example
list = ["cat","dog","lion"]
for animal in list:
print animal
This will print each animal in the list. You can use any other variable name in place of animal.
To open:
f = open('hash.txt', 'w')
To save:
f.write(file_path)

Import the output into a CSV file

Desktop.zip contains multiple text files. fun.py is a python program which will print the name of text files from zip and also the number of lines in each file. Everything is okay up to here. But, It will also import this output in a single CSV file. Code :-
import zipfile, csv
file = zipfile.ZipFile("Desktop.zip", "r")
inputcsv = input("Enter the name of the CSV file: ")
csvfile = open(inputcsv,'a')
#list file names
for name in file.namelist():
print (name)
# do stuff with the file object
for name in file.namelist():
with open(name) as fh:
count = 0
for line in fh:
count += 1
print ("File " + name + "line(s) count = " + str(count))
b = open(inputcsv, 'w')
a = csv.writer(b)
data = [name, str(count)]
a.writerows(data)
file.close()
I am expecting output in CSV file like :-
test1.txt, 25
test2.txt, 10
But I am getting this output in CSV file :-
t,e,s,t,1,.,t,x,t
2,5
t,e,s,t,2,.,t,x,t
1,0
Here, test1.txt and test2.txt are the files in Desktop.zip, and 25 and 10 is the number of lines of those files respectively.
writerows takes an iterable of row-representing iterables. You’re passing it a single row, so it interprets each character of each column as a cell. You don’t want that. Use writerow rather than writerows.
I saw a number of issues:
You should open the csv file only once, before the for loop. Open it inside the for loop will override the information from previous loop iteration
icktoofay pointed out that you should use writerow, not writerows
file is a reserve word, you should not use it to name your variable. Besides, it is not that descriptive
You seem to get the file names from the archive, but open the file from the directory (not the ones inside the archive). These two sets of files might not be identical.
Here is my approach:
import csv
import zipfile
with open('out.csv', 'wb') as file_handle:
csv_writer = csv.writer(file_handle)
archive = zipfile.ZipFile('Desktop.zip')
for filename in archive.namelist():
lines = archive.open(filename).read().splitlines()
line_count = len(lines)
csv_writer.writerow([filename, line_count])
My approach has a couple of issues, which might or might not matter:
I assume files in the archive to be text file
I open, read, and split lines in one operation. This might not work well for very large files
The code in your question has multiple issues, as others have pointed out. The two primary ones are that you're recreating the csv file over and over again for each archive member being processed, and then secondly, are passing csvwriter.writerows() the wrong data. It interprets each item in the list you're passing as a separate row to be added to the csv file.
One way to fix that would be to only open the csv file once, before entering a for loop which counts the line in each member of the archive and writes one row to it at time with a call to csvwriter.writerow().
A slightly different way, shown below, does use writerows() but passes it generator expression that processes the each member one-the-fly instead of calling writerow() repeatedly. It also processes each member incrementally, so it doesn't need to read the whole thing into memory at one time and then split it up in order to get a line count.
Although you didn't indicate what version of Python you're using, from the code in your question, I'm guessing it's Python 3.x, so the answer below has been written and tested with that (although it wouldn't be hard to make it work in Python 2.7).
import csv
import zipfile
input_zip_filename = 'Desktop.zip'
output_csv_filename = input("Enter the name of the CSV file to create: ")
# Helper function.
def line_count(archive, filename):
''' Count the lines in specified ZipFile member. '''
with archive.open(filename) as member:
return sum(1 for line in member)
with zipfile.ZipFile(input_zip_filename, 'r') as archive:
# List files in archive.
print('Members of {!r}:'.format(input_zip_filename))
for filename in archive.namelist():
print(' {}'.format(filename))
# Create csv with filenames and line counts.
with open(output_csv_filename, 'w', newline='') as output_csv:
csv.writer(output_csv).writerows(
# generator expression
[filename, line_count(archive, filename)] # contents of one row
for filename in archive.namelist())
Sample format of content in csv file created:
test1.txt,25
test2.txt,10

How to import data from a CSV file and store it in a variable?

I am extremely new to python 3 and I am learning as I go here. I figured someone could help me with a basic question: how to store text from a CSV file as a variable to be used later in the code. So the idea here would be to import a CSV file into the python interpreter:
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
...
and then extract the text from that file and store it as a variable (i.e. w = ["csv file text"]) to then be used later in the code to create permutations:
print (list(itertools.permutations(["w"], 2)))
If someone could please help and explain the process, it would be very much appreciated as I am really trying to learn. Please let me know if any more explanation is needed!
itertools.permutations() wants an iterable (e.g. a list) and a length as its arguments, so your data structure needs to reflect that, but you also need to define what you are trying to achieve here. For example, if you wanted to read a CSV file and produce permutations on every individual CSV field you could try this:
import csv
with open('some.csv', newline='') as f:
reader = csv.reader(f)
w = []
for row in reader:
w.extend(row)
print(list(itertools.permutations(w, 2)))
The key thing here is to create a flat list that can be passed to itertools.permutations() - this is done by intialising w to an empty list, and then extending its elements with the elements/fields from each row of the CSV file.
Note: As pointed out by #martineau, for the reasons explained here, the file should be opened with newline='' when used with the Python 3 csv module.
If you want to use Python 3 (as you state in the question) and to process the CSV file using the standard csv module, you should be careful about how to open the file. So far, your code and the answers use the Python 2 way of opening the CSV file. The things has changed in Python 3.
As shengy wrote, the CSV file is just a text file, and the csv module gets the elements as strings. Strings in Python 3 are unicode strings. Because of that, you should open the file in the text mode, and you should supply the encoding. Because of the nature of CSV file processing, you should also use the newline='' when opening the file.
Now extending the explanation of Burhan Khalid... When reading the CSV file, you get the rows as lists of strings. If you want to read all content of the CSV file into memory and store it in a variable, you probably want to use the list of rows (i.e. list of lists where the nested lists are the rows). The for loop iterates through the rows. The same way the list() function iterates through the sequence (here through the sequence of rows) and build the list of the items. To combine that with the wish to store everything in the content variable, you can write:
import csv
with open('some.csv', newline='', encoding='utf_8') as f:
reader = csv.reader(f)
content = list(reader)
Now you can do your permutation as you wish. The itertools is the correct way to do the permutations.
import csv
data = csv.DictReader(open('FileName.csv', 'r'))
print data.fieldnames
output = []
for each_row in data:
row = {}
try:
p = dict((k.strip(), v) for k, v in p.iteritems() if v.lower() != 'null')
except AttributeError, e:
print e
print p
raise Exception()
//based on the number of column
if p.get('col1'):
row['col1'] = p['col1']
if p.get('col2'):
row['col2'] = p['col2']
output.append(row)
Finally all data stored in output variable
Is this what you need?
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f, delimiter=',')
rows = list(reader)
print('The csv file had {} rows'.format(len(rows)))
for row in rows:
do_stuff(row)
do_stuff_to_all_rows(rows)
The interesting line is rows = list(reader), which converts each row from the csv file (which will be a list), into another list rows, in effect giving you a list of lists.
If you had a csv file with three rows, rows would be a list with three elements, each element a row representing each line in the original csv file.
If all you care about is to read the raw text in the file (csv or not) then:
with open('some.csv') as f:
w = f.read()
will be a simple solution to having w="csv, file, text\nwithout, caring, about columns\n"
You should try pandas, which work both with Python 2.7 and Python 3.2+ :
import pandas as pd
csv = pd.read_csv("your_file.csv")
Then you can handle you data easily.
More fun here
First, a csv file is a text file too, so everything you can do with a file, you can do it with a csv file. That means f.read(), f.readline(), f.readlines() can all be used. see detailed information of these functions here.
But, as your file is a csv file, you can utilize the csv module.
# input.csv
# 1,david,enterprise
# 2,jeff,personal
import csv
with open('input.csv') as f:
reader = csv.reader(f)
for serial, name, version in reader:
# The csv module already extracts the information for you
print serial, name, version
More details about the csv module is here.

Categories

Resources