why there is no content in the "file object?"
Tried changing to append and there's content since the second run. What am I missing here?
code below:
import random
from io import StringIO
class WriteMyStuff(object):
def __init__(self, writer):
self.writer = writer
def write(self):
write_text = "this is a silly message\n"
self.writer.write(write_text)
fh = open('test.txt', 'w')
w1 = WriteMyStuff(fh)
w1.write()
fh.close
sioh = StringIO()
w2 = WriteMyStuff(sioh)
w2.write()
print("file object: ", open('test.txt', 'r').read())
print("StringIO object:", sioh.getvalue())
Thanks!
This happened because you forgot to call the close method properly in line 17. You called it like an attribute where it needs to be called with the parenthesis .close(). Here's, the fixed version:
import random
from io import StringIO
class WriteMyStuff(object):
def __init__(self, writer):
self.writer = writer
def write(self):
write_text = "this is a silly message\n"
self.writer.write(write_text)
fh = open("test.txt", "w")
w1 = WriteMyStuff(fh)
w1.write()
fh.close()
sioh = StringIO()
w2 = WriteMyStuff(sioh)
w2.write()
print("file object: ", open("test.txt", "r").read())
print("StringIO object:", sioh.getvalue())
This will print out:
file object: this is a silly message
StringIO object: this is a silly message
This code still has one subtle bug, it hasn't closed the second file handler object in the line before the last line.
You can use contextmanages if you don't want to handle closing the file handlers manually. Consider this example:
import random
from io import StringIO
class WriteMyStuff(object):
def __init__(self, writer):
self.writer = writer
def write(self):
write_text = "this is a silly message\n"
self.writer.write(write_text)
with open("test.txt", "w") as fh:
w1 = WriteMyStuff(fh)
w1.write()
sioh = StringIO()
w2 = WriteMyStuff(sioh)
w2.write()
with open("test.txt", "r") as f:
print("file object: ", f.read())
print("StringIO object:", sioh.getvalue())
The with block takes care of closing the file handler after you go out of scope.
Related
This is one of the MIT python project questions, but it's basically written for python 2.x users, so is there any way to fix the following code to operate in the latest python 3?
The current code is raising "ValueError: can't have unbuffered text I/O"
WORDLIST_FILENAME = "words.txt"
def load_words():
print("Loading word list from file...")
inFile = open(WORDLIST_FILENAME, 'r', 0)
# wordlist: list of strings
wordlist = []
for line in inFile:
wordlist.append(line.strip().lower())
print(" ", len(wordlist), "words loaded.")
return wordlist
From open's docstring:
... buffering is an optional integer used to set the buffering policy.
Pass 0 to switch buffering off (only allowed in binary mode) ...
So change inFile = open(WORDLIST_FILENAME, 'r', 0)
to
inFile = open(WORDLIST_FILENAME, 'r'), or to
inFile = open(WORDLIST_FILENAME, 'rb', 0) if you really need it (which I doubt).
I could overcome this error by using code from this answer:
class Unbuffered(object):
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
def writelines(self, datas):
self.stream.writelines(datas)
self.stream.flush()
def __getattr__(self, attr):
return getattr(self.stream, attr)
import sys
sys.stdout = Unbuffered(sys.stdout)
You can flush to the file after every write.
outFile = open(outputfile, "w",encoding='utf-8')
inFile = open(inputfile, "r",encoding='utf-8')
while inFile:
line = inFile.readline()[:-1]
outFile.write(line)
outFile.flush()
I have data which is being accessed via http request and is sent back by the server in a comma separated format, I have the following code :
site= 'www.example.com'
hdr = {'User-Agent': 'Mozilla/5.0'}
req = urllib2.Request(site,headers=hdr)
page = urllib2.urlopen(req)
soup = BeautifulSoup(page)
soup = soup.get_text()
text=str(soup)
The content of text is as follows:
april,2,5,7
may,3,5,8
june,4,7,3
july,5,6,9
How can I save this data into a CSV file.
I know I can do something along the lines of the following to iterate line by line:
import StringIO
s = StringIO.StringIO(text)
for line in s:
But i'm unsure how to now properly write each line to CSV
EDIT---> Thanks for the feedback as suggested the solution was rather simple and can be seen below.
Solution:
import StringIO
s = StringIO.StringIO(text)
with open('fileName.csv', 'w') as f:
for line in s:
f.write(line)
General way:
##text=List of strings to be written to file
with open('csvfile.csv','wb') as file:
for line in text:
file.write(line)
file.write('\n')
OR
Using CSV writer :
import csv
with open(<path to output_csv>, "wb") as csv_file:
writer = csv.writer(csv_file, delimiter=',')
for line in data:
writer.writerow(line)
OR
Simplest way:
f = open('csvfile.csv','w')
f.write('hi there\n') #Give your csv text here.
## Python will convert \n to os.linesep
f.close()
You could just write to the file as you would write any normal file.
with open('csvfile.csv','wb') as file:
for l in text:
file.write(l)
file.write('\n')
If just in case, it is a list of lists, you could directly use built-in csv module
import csv
with open("csvfile.csv", "wb") as file:
writer = csv.writer(file)
writer.writerows(text)
I would simply write each line to a file, since it's already in a CSV format:
write_file = "output.csv"
with open(write_file, "wt", encoding="utf-8") as output:
for line in text:
output.write(line + '\n')
I can't recall how to write lines with line-breaks at the moment, though :p
Also, you might like to take a look at this answer about write(), writelines(), and '\n'.
To complement the previous answers, I whipped up a quick class to write to CSV files. It makes it easier to manage and close open files and achieve consistency and cleaner code if you have to deal with multiple files.
class CSVWriter():
filename = None
fp = None
writer = None
def __init__(self, filename):
self.filename = filename
self.fp = open(self.filename, 'w', encoding='utf8')
self.writer = csv.writer(self.fp, delimiter=';', quotechar='"', quoting=csv.QUOTE_ALL, lineterminator='\n')
def close(self):
self.fp.close()
def write(self, elems):
self.writer.writerow(elems)
def size(self):
return os.path.getsize(self.filename)
def fname(self):
return self.filename
Example usage:
mycsv = CSVWriter('/tmp/test.csv')
mycsv.write((12,'green','apples'))
mycsv.write((7,'yellow','bananas'))
mycsv.close()
print("Written %d bytes to %s" % (mycsv.size(), mycsv.fname()))
Have fun
What about this:
with open("your_csv_file.csv", "w") as f:
f.write("\n".join(text))
str.join() Return a string which is the concatenation of the strings in iterable.
The separator between elements is
the string providing this method.
In my situation...
with open('UPRN.csv', 'w', newline='') as out_file:
writer = csv.writer(out_file)
writer.writerow(('Name', 'UPRN','ADMIN_AREA','TOWN','STREET','NAME_NUMBER'))
writer.writerows(lines)
you need to include the newline option in the open attribute and it will work
https://www.programiz.com/python-programming/writing-csv-files
I have a CSV file which has three columns. The third column "row[02]" has a listing of IP's which contains a list of IP's that are comma delimited. I would like to turn the following:
"column01", "column02", "192.168.1.1, 192.168.2.1, 192.168.3.1"
into (minus the bullets):
column01, column02, 192.168.1.1
column01, column02, 192.168.2.1
column01, column02, 192.168.3.1
Provided is my code, but the output keeps displaying the following:
row01, row02, 192.168.1.1, 192.168.2.1, 192.168.3.1
Please let me know if any other information is needed. Thanks in advance.
Original Code:
#!/usr/bin/python
import csv, sys, time, logging
s = time.strftime('%Y%m%d%H%M%S')
# Create exception file from standard output
class Logger(object):
def __init__(self):
self.terminal = sys.stdout
self.log = open((s) + "_" + sys.argv[1], "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def main():
# Start screen capture to output into CSV file
sys.stdout = Logger()
# File input argument
with open(sys.argv[1], "rb") as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
print row[0], ",", row[1], ",", row[2]
if __name__=='__main__':
main()
Updated Code:
#!/usr/bin/python
import csv, sys, time, logging
s = time.strftime('%Y%m%d%H%M%S')
# Create exception file from standard output
class Logger(object):
def __init__(self):
self.terminal = sys.stdout
self.log = open((s) + "_" + sys.argv[1], "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def main():
# Start screen capture to output file
sys.stdout = Logger()
# File input argument
with open(sys.argv[1], "rb") as f:
reader = csv.reader(f, delimiter=',', skipinitialspace=True)
for row in reader:
network = row[0].replace(" ","")
network_group = row[1].replace(" ","")
address = row[2].replace(',','\n').replace(" ","")
if "-" in address: #parse network ranges
try:
print IP(address), network, network_group
except:
netrange = address.replace('-'," ").replace(" ",",")
print netrange, ",", network, ",", network_group
else:
print address, ",", network, ",", network_group
if __name__=='__main__':
main()
The reason it's printing this:
row01, row02, 192.168.1.1, 192.168.2.1, 192.168.3.1
Is that you asked it to do exactly that for each row:
for row in reader:
print row[0], ",", row[1], ",", row[2]
If you want it to do something different, you have to tell it to do something different. It can't read your mind. So, if you want to, e.g., split row[2] on commas, you need to write some code that does that. Like this:
for row in reader:
addresses = row[2].split(", ")
for address in addresses:
print row[0], ",", row[1], ",", address
I have a block of code that reads and writes to csv.
The reader takes a file "x" compares it to file "y" and returns new file "z"
Now I wrote a GUI program using tkinter that returns a filepath to a textbox in the GUI program.
The filepath I get as follows:
def OnButtonClick1(self):
self.labelVariable.set( self.entryVariable.get())
self.entry.focus_set()
self.entry.selection_range(0, tkinter.END)
filename = askopenfilename()
with open(filename,'r') as f:
for file in f:
data = f.read()
self.entry.insert(0,filename)
How can I use this filepath above in my reader to represent "myfile" in the code below?
#Opening my enquiry list .cvs file
datafile = open('myfile', 'r')
datareader = csv.reader(datafile)
n1 = []
for row in datareader:
n1.append(row)
n = list(itertools.chain(*n1))
print()
Help much appriciated!!!
Maybe something like this
class gui:
...
def OnButtonClick1(self):
self.labelVariable.set( self.entryVariable.get())
self.entry.focus_set()
self.entry.selection_range(0, tkinter.END)
filename = askopenfilename()
self.filename = filename
with open(filename,'r') as f:
for file in f:
data = f.read()
self.entry.insert(0,filename)
def GetFilename(self):
return self.filename
...
gui_object = gui()
...
#Opening my enquiry list .cvs file
myfile = gui_object.GetFilename()
datafile = open(myfile, 'r')
datareader = csv.reader(datafile)
n1 = []
for row in datareader:
n1.append(row)
n = list(itertools.chain(*n1))
trying to process text file and would like to see output in idle as well as redirected to text file. due to text formatting, i need to keep statement in print function (end = ''). i am looking for a way to use "end = ''" and "file=output_file" simultaneously with print function.
import re
input_file = open ('E:\input.txt','r')
output_file = open ('E:\output.txt','w')
for line in input_file:
if re.match('ab|cd', line):
print ('line with ab or cd: ', end = '',file=output_file )
print (line, end = '',file=output_file)
print (' --------', file=output_file)
print (' --------',file=output_file)
print ('!',file=output_file)
else:
print (line,file=output_file)
To write to several places using a single print(), you could define a file-like object:
class TeeFile(object):
def __init__(self, *files):
self.files = files
def write(self, data):
for f in self.files:
f.write(data)
def flush(self):
for f in self.files:
f.flush()
Example:
import sys
file = TeeFile(sys.stderr, output_file)
print("abc", end="", file=file)
file.flush()