Python: Having trouble reading in files - python

I am having trouble reading in files through Python 2.7. I prompt the user to load a file, and once the filename is given, the program will simply load and print the lines in the file.
filename = raw_input("Filename to load: ")
print load_records(students, filename)
def load_records(students, filename):
#loads student records from a file
records = []
in_file = open(filename, "r")
for line in in_file:
print line
However, even if the entire file path is specified, the program throws a 'ValueError: mixing iterations and read methods would lose data.'

Related

printing the content of a file, but getting an int as an output (number of characters in the file) in Python

I wrote a function that copies the content of one file to a new file.
the function gets 2 parameters:
the directory of the copied file
the directory of the new file.
When I try to print the content of the copied file, I get the content of the file (which is what I want), But when I try to do the same thing with the new file, I get the number of characters inside the file (14 in this case).
I don't understand why do I get 2 different outputs with the same (at list as per my understanding) lines of code.
Would be happy to get some help, thank you!
Here's my code:
# creating the file that's going to be copied:
with open(source_link, 'w') as f:
f.write('Copy this file')
# the function:
def copy_file_content(source, destination):
# getting the content of the copied file:
f1 = open(source, 'r')
copied_file = f1.read()
f1.close()
# putting the content of the copied file in the new file:
f2 = open(destination, 'w')
new_file = f2.write(copied_file)
f2.close
# print old file:
print(copied_file)
print('***')
# print new file:
print(new_file)
copy_file_content(source = source_link, destination = dest_link)
Output:
Copy this file
***
14
As referenced in Python documentation:
f.write(string) writes the contents of string to the file, returning the number of characters written.
Opposed to f.read(), which returns file contents.
If you want to read contents of copied_file, you will need to open it again in read mode:
with open(destination, 'r') as f:
new_file = f.read(copied_file)
.read() returns the file contents, which is why when copied_file is set to f1.read(), you can print the contents out. However, .write() performs the write operation on the file and then returns the number of characters written.
Therefore new_file contains the number of characters written. Rather than setting the value of new_file to f2.write(), you must open the new file again in read mode, and then perform file.read()
def copy_file_content(source, destination):
# getting the content of the copied file:
with open(source, 'r') as f1:
copied_file = f1.read()
# putting the content of the copied file in the new file:
with open(destination, 'w') as f2:
f2.write(copied_file)
with open(destination, "r") as f2_read:
new_file = f2_read.read()
# print old file:
print(copied_file)
print('***')
# print new file:
print(new_file)
copy_file_content(source = source_link, destination = dest_link)

Opening and reading a file of names converting to usernames and storing in another file

Foundation year programming student here. I'm trying to do some batch mode processing, Taking a list of names in a file, opening said file, reading it, assigning a username each name in the file and then storing said names in another file.
Here is my code:
# A program which takes a list of names from a file, creates a new file
# and makes a username based on each name into it.
#first open each file
import string
def main():
infileName = raw_input("What file are the names in")
outfileName = raw_input("What file are the usernames going in?")
#open the files
infile = open(infileName, "r")
outfile = open(outfileName, "w")
data = infile.read()
print data
main()
#process each line in the file
for line in infile:
#get the first and last names from line
first, last = string.split(line)
#create a username
uname = string.lower(first[0]+last[:7])
#write it to output file
outfile.write(uname+"\n")
#close both files
infile.close()
outfile.close()
print "The usernames have been written to, ", outfileName
It all seems fine except it comes out with the error code:
Traceback (most recent call last):
File "C:/Users/Manol/OneDrive/Documents/Uni/Programming/File Processing File/BatchUsernames.py", line 23, in <module>
for line in infile:
NameError: name 'infile' is not defined
>>>
I don't understand as I thought I had defined it on line 13
infile = open(infileName, "r")
If anyone could point out what I'm doing wrong it would be much appreciated.
Thanks for you time
Manos
You defined it in your main() function, so it is a local variable. Any function outside of main() won't recognize it. You should probably also use data instead but again, that is a local variable. A possible solution could be something like this:
import string
def main():
infileName = raw_input("What file are the names in")
outfileName = raw_input("What file are the usernames going in?")
#open the files
infile = open(infileName, "r")
outfile = open(outfileName, "w")
data = infile.read()
for line in data:
first, last = string.split(line)
uname = string.lower(first[0]+last[:7])
outfile.write(uname+"\n")
infile.close()
outfile.close()
print(data)
print("The usernames have been written to, ", outfileName)
main()

python writing to a different text file every time

I've tried a few different methods of doing this but each one has errors or will only function in specific ways.
randomData = ("Some Random stuff")
with open("outputFile.txt", "a") as file:
file.write(randomData)
exit()
What i'm trying to to is write to the "outputFile.txt" file and then next output to a different file such as "outputFileTwo.txt".
If you need different filename at every start then you have to save in other file (ie. config.txt) information about current filename. It can be number which you will use in filename (file1.txt, file2.txt, etc.).
And at start read number from config.txt, increase this number, use in filename, and write number again in config.txt.
Or you can use modul datetime to use current date and time in filename.
https://docs.python.org/3.5/library/datetime.html
There is also module to generate temporary (random and unique) filename.
https://docs.python.org/3.5/library/tempfile.html
If you're writing the same data to multiple files, you can do something like this:
data = "some data"
files = ['file1.txt', 'file2.txt', 'file3.txt']
for file in files:
with open(file, "a") as f:
f.write(data)
Based on your comment concerning a new file name for each run:
import time
randomData = ("Some Random stuff")
t,s = str(time.time()).split('.')
filename = t+".txt"
print ("writing to", filename)
with open(filename, "a") as file:
file.write(randomData)

Error when trying to read and write multiple files

I modified the code based on the comments from experts in this thread. Now the script reads and writes all the individual files. The script reiterates, highlight and write the output. The current issue is, after highlighting the last instance of the search item, the script removes all the remaining contents after the last search instance in the output of each file.
Here is the modified code:
import os
import sys
import re
source = raw_input("Enter the source files path:")
listfiles = os.listdir(source)
for f in listfiles:
filepath = source+'\\'+f
infile = open(filepath, 'r+')
source_content = infile.read()
color = ('red')
regex = re.compile(r"(\b be \b)|(\b by \b)|(\b user \b)|(\bmay\b)|(\bmight\b)|(\bwill\b)|(\b's\b)|(\bdon't\b)|(\bdoesn't\b)|(\bwon't\b)|(\bsupport\b)|(\bcan't\b)|(\bkill\b)|(\betc\b)|(\b NA \b)|(\bfollow\b)|(\bhang\b)|(\bbelow\b)", re.I)
i = 0; output = ""
for m in regex.finditer(source_content):
output += "".join([source_content[i:m.start()],
"<strong><span style='color:%s'>" % color[0:],
source_content[m.start():m.end()],
"</span></strong>"])
i = m.end()
outfile = open(filepath, 'w+')
outfile.seek(0)
outfile.write(output)
print "\nProcess Completed!\n"
infile.close()
outfile.close()
raw_input()
The error message tells you what the error is:
No such file or directory: 'sample1.html'
Make sure the file exists. Or do a try statement to give it a default behavior.
The reason why you get that error is because the python script doesn't have any knowledge about where the files are located that you want to open.
You have to provide the file path to open it as I have done below. I have simply concatenated the source file path+'\\'+filename and saved the result in a variable named as filepath. Now simply use this variable to open a file in open().
import os
import sys
source = raw_input("Enter the source files path:")
listfiles = os.listdir(source)
for f in listfiles:
filepath = source+'\\'+f # This is the file path
infile = open(filepath, 'r')
Also there are couple of other problems with your code, if you want to open the file for both reading and writing then you have to use r+ mode. More over in case of Windows if you open a file using r+ mode then you may have to use file.seek() before file.write() to avoid an other issue. You can read the reason for using the file.seek() here.

Python non-specific write exception

Currently teaching myself Python, and learning file I/O by writing a script to both read from and add text to an existing file. The script runs up until I call the write() method, at which point it throws out a non-specific exception - this is the traceback:
File "test.py", line 13, in <module>
f.write(txt)
IOError: [Errno 0] Error
My code:
from sys import argv
script, filename = argv
f = open(filename, 'a+')
print("The contents of %s are:") % filename
print f.read()
txt = raw_input("What would you like to add? ")
f.write(txt)
print("The new contents are:")
print f.read()
f.close()
My environment is Python 2.7.3 in Win7, PowerShell, and Notepad++.
What is causing this? How would I fix it? In my understanding, the a+ access mode should allow me to both read and append to the file. Changing the access mode to r+ yields the same exception.
Clarifications:
I have an existing text file (a.txt) with a single word in it that I pass as an argument to the script, like so:
python test.py a.txt
I am under an admin account in Windows.
Results:
At the minimum, adding two seek() commands fixes the issue - detailed in the answer post.
A problem when one tries to add a text of little size: it remains in the buffer, that keeps the text before the real writing is done after receiving more data.
So, to be sure to write really, do as it is described in the doc concerning os.fsync() and flush()
By the way, it is better to use the with statement.
And it's still more better to use binary mode. In your case, there shouldn't be a problem because you just add text after the reading and just use seek(o,o) . But when one wants to move correctly the file's pointer into the bytes of the file, it is absolutely necessary to use binary mode [ the 'b' in open(filename, 'rb+') ]
I personnaly never use 'a+', I've never understood what are its effects.
from sys import argv
from os import fsync
script, filename = argv
with open(filename, 'rb+') as f:
print("The contents of %s are:") % filename
print f.read()
f.seek(0,2)
txt = raw_input("What would you like to add? ")
f.write(txt)
f.flush()
fsync(f.fileno())
f.seek(0,0)
print("The new contents are:")
print f.read()
For some reason print f.read() doesn't work for me on OS X when you have opened the file in a+ mode.
On Max OS X, changing the open mode to r+ and then adding a f.seek(0) line before the second read makes it work. Sadly, this doesn't help windows.
This is the working code on Mac OS:
from sys import argv
script, filename = argv
f = open(filename, 'r+')
print("The contents of %s are:") % filename
print f.read()
txt = raw_input("What would you like to add? ")
f.write(txt)
print("The new contents are:")
f.seek(0)
print f.read()
f.close()
This is the only way I could get it to work on windows 7:
from sys import argv
script, filename = argv
f = open(filename, 'r')
print("The contents of %s are:") % filename
print f.read()
f.close()
txt = raw_input("What would you like to add? ")
f = open(filename, 'a')
f.write(txt)
f.close()
f = open(filename, 'r')
print("The new contents are:")
print f.read()
f.close()
Which seems super hacky. This should also work on Mac OS X too.

Categories

Resources