I am new to learning python. I don't understand why print command will output all variables on screen but write command to file only writes 2 first two variables.
print "Opening the file..."
target = open(filename, 'a+')
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
line4 = line1 + "\n" + line2 + "\n" + line3
# This command prints all 3 (line1,line2,line3) variables on terminal
print line4
#This command only writes line1 and line2 variables in file
target.write(line4)
print "close the file"
target.close()
The OS normally flushes the write buffer after a newline.
When you open(filename, 'a+') the file, these same rules apply by default.
From the docs: https://docs.python.org/2/library/functions.html#open
The optional buffering argument specifies the file’s desired buffer
size: 0 means unbuffered, 1 means line buffered, any other positive
value means use a buffer of (approximately) that size (in bytes). A
negative buffering means to use the system default, which is usually
line buffered for tty devices and fully buffered for other files. If
omitted, the system default is used.
Call target.close() to ensure everything is written out ("flushed") to the file (as per the comment below, close flushes for you). You can manually flush with target.flush().
print "Opening the file..."
target = open(filename, 'a+')
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
line4 = line1 + "\n" + line2 + "\n" + line3
# This command prints all 3 (line1,line2,line3) variables on terminal
print line4
target.write(line4)
target.close() #flushes
Alternatively, using the with keyword will automatically close the file when we leave the with block: (see What is the python keyword "with" used for?)
print "Opening the file..."
with open(filename, 'a+') as target:
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
line4 = line1 + "\n" + line2 + "\n" + line3
# This command prints all 3 (line1,line2,line3) variables on terminal
print line4
target.write(line4)
Related
Here is the code I have to extract blocks of text of a file that starts with "Start Text" until it encounters another "Start Text".
with open('temp.txt', "r") as f:
buff = []
i = 1
for line in f:
if line.strip(): skips the empty lines
buff.append(line)
if line.startswith("Start Text"):
output = open('file' + '%d.txt' % i, 'w')
output.write(''.join(buff))
output.close()
i += 1
buff = [] # buffer reset
INPUT: "temp.txt" has the following structure:
Start Text - ABCD
line1
line2
line3
Start Text - EFG
line4
Start Text - P3456
line5
line6
DESIRED OUTPUT: I am trying to create multiple text files below with extracted blocks of texts.
file1.txt
Start Text - ABCD
line1
line2
line3
file2.txt
Start Text - EFG
line4
file3.txt
Start Text - P3456
line5
line6
UNDESIRED OUTPUT (What the code produces)
file1.txt
Start Text - ABCD
file2.txt
Start Text - EFG
line1
line2
line3
file3.txt
line4
Start Text - P3456
Here is the issue I am facing. The code creates three files but does not write “Start Text” lines into their respective text blocks. I am not sure what I am missing. I will appreciate any pointers.
When the code sees "Start Text" in a line, it writes that line and all the previous lines to the output file.
This explains why the first output file contains only the header -- that is the first line in the input file, so obviously there aren't any previous lines.
It seems like what you really want is for the header and the following lines to be written.
I've updated your code to not write a file after seeing the very first header, and also to write a file after the input file is exhausted.
buff = []
i = 1
with open('temp.txt', "r") as f:
for line in f:
if line.startswith("Start Text"):
# write a file only if buff isn't empty. (if it is
# empty, this must be the very first header, so we
# don't need to write an output file yet)
if buff:
output = open('file' + '%d.txt' % i, 'w')
output.write(''.join(buff))
output.close()
i += 1
buff = [] # buffer reset
if line.strip():
buff.append(line)
# write the final section
if buff:
output = open('file' + '%d.txt' % i, 'w')
output.write(''.join(buff))
output.close()
You're almost there. See how when you check for startswith(), then write out the buffer, and clean the buffer. As it returns to the loop, if hasn't stored the line when entering this if statement - this line is lost. Try adding it to the new buffer for the next round of lines.
...
buff = [] # buffer reset
buff.append(line) # add 'Start Text' line to next buffer
Note that your code currently will never write out the final block of text. Consider to write out the last buffer as well (i.e., when no line is left).
[EDIT after question edit]
As the other answer replies, the check for startswith() causes a write to file after the line is found. However, the line has already been added to the buffer. Try switching the statements, to first detect the startswith, then write everything out if it was the case (if the buffer is not empty!), then continue by adding the line to the buffer.
(the note still stands)
def parse_file(fname):
with open(fname, "r") as f:
buff = []
for line in f:
if line.strip(): # skips the empty lines
if line.startswith("Start Text") and buff:
yield ''.join(buff)
buff = []
buff.append(line)
for idx, data in enumerate(parse_file('sample.txt'), start=1):
with open(f'file{idx}.txt', 'w') as f:
f.write(data)
I don't think you need to build a buffer. You can just process line by line as you iterate over the input file.
class MyTempFile():
def __init__(self):
self.fd = None
self.newfile = None
def __enter__(self):
return self
def __exit__(self, *args):
self.closefd()
self.newfile = None
def closefd(self):
if self.fd is not None:
self.fd.close()
self.fd = None
def newfile_impl(self):
i = 0
while True:
self.closefd()
i += 1
self.fd = open(f'temp{i}.txt', 'w')
yield
def write(self, data):
if self.fd is not None and data.strip():
self.fd.write(data)
def next_file(self):
if self.newfile is None:
self.newfile = self.newfile_impl()
next(self.newfile)
with MyTempFile() as mtf:
with open('temp.txt') as infile:
for line in infile:
if line.startswith('Start Text'):
mtf.next_file()
mtf.write(line)
I am trying to break a line with \n with optparse. Example: line1 \n line2
But when I type \n it doesn't break it just prints it as line1 \n line2, instead of doing a break. Here is my code:
import optparse
import sys
def main():
progparse = optparse.OptionParser("usage " + "--message <text here>")
progparse.add_option("--message", dest="msg_txt", type="string", help="Type the message you want to send")
msg_txt = ""
if (options.msg_txt == None):
print(progparse.usage)
sys.exit()
print(options.msg_txt)
if __name__ == '__main__':
main()
If I just do a simple print statment with \n then it will break the line, why doesn't it do it when using optparse?
option1, use real new line in your input:
$ python3 test.py --message "line1
> line2
> line3"
line1
line2
line3
option2, eval \n as real new line with ast.literal_eval:
print(ast.literal_eval('"' + options.msg_txt + '"'))
note this may raise an exception for ill-formed input.
I tried to remove the unwanted characters / # http form each line
codes below:
import csv
with open('C:\\project\\in.csv','r') as input_file:
with open('C:\\project\\out.csv','w') as output_file:
for L in input_file:
if L.endswith("/"):
newL=L.replace("/","")
output_file.write(newL)
elif L.find("#"):
newL,sep,tail=L.partition("#")
output_file.write(newL)
elif L.startswith('http:'):
newL=L.replace('http:','https:')
output_file.write(newL)
here is the mini example in.csv file for testing:
line1/
line2#sdgsgs
https://line3
http://line4
line5/
after make clean, I want it to be like :
line1
line2
https://line3
https://line4
line5
But the result not what I want, Can some one give me a hand.
Many Thanks, Henry
In this version a line can contain all of the replacement chars:
#!/usr/bin/env python
import csv
Output = []
with open('C:\\project\\in.csv', 'r') as input_file:
for line in input_file:
line = line.strip()
if line.endswith("/"):
line = line.replace("/", "")
if "#" in line:
line, sep, tail = line.partition("#")
if line.startswith('http:'):
line = line.replace('http:', 'https:')
Output.append(line)
with open('C:\\project\\out.csv', 'w') as output_file:
for output in Output:
output_file.write("{}\n".format(output))
Will output:
line1
line2
https://line3
https://line4
line5
I'm completing exercise 16 from Learn Python the Hard Way and it's asking this question:
Write a script similar to the last exercise that uses read and argv to
read the file you just created.
I'm attempting to use the 'read' function in order to have the script automatically run and display the text file that the script creates. But nothing shows up when I run everything, it's just an extra blank space before "close it". How do I get it to display anything?
from sys import argv
script, filename = argv
txt = open(filename)
print "Erase %r" % filename
print "hit CTRL-C (^C)."
print "hit RETURN."
raw_input("?")
print "Opening the file..."
target = open(filename, 'w')
print "Truncating the file."
target.truncate()
print "Need 3 lines."
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
print "Write these to a file"
target.write("{0}\n{1}\n{2}\n".format(line1, line2, line3))
print txt.read()
print "Close it."
target.close()
You should close the file after writing and then open it again for reading:
from sys import argv
script, filename = argv
print "Erase %r" % filename
print "hit CTRL-C (^C)."
print "hit RETURN."
raw_input("?")
print "Opening the file..."
with open(filename, 'w') as target:
print "Truncating the file."
target.truncate()
print "Need 3 lines."
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
print "Write these to a file"
target.write("{0}\n{1}\n{2}\n".format(line1, line2, line3))
txt = open(filename)
print txt.read()
print "Close it."
target.close()
The second version (without "with as" structure):
from sys import argv
script, filename = argv
print "Erase %r" % filename
print "hit CTRL-C (^C)."
print "hit RETURN."
raw_input("?")
print "Opening the file..."
target = open(filename, 'w')
print "Truncating the file."
target.truncate()
print "Need 3 lines."
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
print "Write these to a file"
target.write("{0}\n{1}\n{2}\n".format(line1, line2, line3))
print "Close it."
target.close()
txt = open(filename)
print txt.read()
I'm trying to write a program similar to this guy's Learn Python the Hard Way program, near the top of the page.
http://learnpythonthehardway.org/book/ex16.html
This is my version below. But it tells me off for using "%r" at the end, why does it do that? I thought that's what you're meant to do in parenthesis.
# -- coding: utf-8 --
from sys import argv
script, filename = argv
print "Would you like file %r to be overwritten?" % filename
print "Press RETURN if you do, and CTRL-C otherwise."
raw_input('> ')
print "Opening the file ..."
target = open(filename, 'w')
target.truncate()
print "Now type three lines to replace the contents of %r" % filename
line1 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
print "The lines below have now overwritten the previous contests."
target.write("%r\n%r\n%r") % (line1, line2, line3)
target.close()
You need to place the % operator directly after the format string. Take the parenthesis here:
target.write("%r\n%r\n%r") % (line1, line2, line3)
# --^
And move it to the end of the line:
target.write("%r\n%r\n%r" % (line1, line2, line3))
# --^
Also, I would like to mention that performing string formatting operations with % is frowned upon these days. The modern approach is to use str.format:
target.write("{0!r}\n{1!r}\n{2!r}".format(line1, line2, line3))