I am studying python file I/O. I made a simple program(main.py).
My goal is read line by line and write line by line.
fstream = open("input2.txt", 'r');
line = fstream.readline()
while line:
print(line);
line = fstream.readline()
fstream.close()
below are my input2.txt file
start.
hello world.
hello python.
I am studying file I/O in python
end.
when I run python program
python main.py
Then, result is ...
start.
hello world.
hello python.
I am studying file I/O in python
end.
That is not the same as I expected.
So I modified the main.py
fstream = open("input2.txt", 'r');
line = fstream.read().split("\n")
while line:
print(line);
line = fstream.read().split("\n")
fstream.close()
However my program diged into infinite loop.
picture of infinite loop
To solve this problem what should I do?
The result I expected is the following.
start.
hello world.
hello python.
I am studying file I/O in python
end.
The print function will automatically add a new line character. So
print msg
will print content of variable msg followed by a new line
If you do not want python to print the trailing new line, you have to add a comma to the end. This will print msg without the trailing newline. And if msg already has a new line which is the case when reading new lines from a file, you will see a single new line in place of double new lines.
print msg,
If you are using python 3 where print is called as a function, you can specify the end argument. See https://docs.python.org/3/library/functions.html#print
print(msg, end = '')
First of all, use a with statement to open the file so that you don't need to close it explicitly. Second, don't use a while loop for this; you can iterate over a file directly. Third, use the rstrip method to remove any trailing whitespace from line you read (or rstrip('\n') to remove only trailing newlines):
with open("input2.txt", 'r') as fstream:
for line in fstream:
line = line.rstrip('\n')
print(line)
In addition to the answers above; You can also use .splitlines()
fstream = open("input2.txt", 'r');
line = fstream.readline().splitlines()
while line:
print(line[0]);
line = fstream.readline().splitlines()
fstream.close()
Related
I'm trying to read a log file, written line by line, via readline.
I'm surprised to observe the following behaviour (code executed in the interpreter, but same happens when variations are executed from a file):
f = open('myfile.log')
line = readline()
while line:
print(line)
line = f.readline()
# --> This displays all lines the file contains so far, as expected
# At this point, I open the log file with a text editor (Vim),
# add a line, save and close the editor.
line = f.readline()
print(line)
# --> I'm expecting to see the new line, but this does not print anything!
Is this behaviour standard? Am I missing something?
Note: I know there are better way to deal with an updated file for instance with generators as pointed here: Reading from a frequently updated file. I'm just interested in understanding the issue with this precise use case.
For your specific use case, the explanation is that Vim uses a write-to-temp strategy. This means that all writing operations are performed on a temporary file.
On the contrary, your scripts reads from the original file, so it does not see any change on it.
To further test, instead of Vim, you can try to directly write on the file using:
echo "Hello World" >> myfile.log
You should see the new line from python.
for following your file, you can use this code:
f = open('myfile.log')
while True:
line = readline()
if not line:
print(line)
I'm using Python 2.7.15, Windows 7
Context
I wrote a script to read and tokenize each line of a FileZilla log file (specifications here) for the IP address of the host that initiated the connection to the FileZilla server. I'm having trouble parsing the log text field that follows the > character. The script I wrote uses the:
with open('fz.log','r') as rh:
for lineno, line in rh:
pass
construct to read each line. That for-loop stopped prematurely when it encountered a log text field that contained the SOH and SUB characters. I can't show you the log file since it contains sensitive information but the crux of the problem can be reproduced by reading a textfile that contains those characters on a line.
My goal is to extract the IP addresses (which I can do using re.search()) but before that happens, I have to remove those control characters. I do this by creating a copy of the log file where the lines containing those control characters are removed. There's probably a better way, but I'm more curious why the for-loop just stops after encountering the control characters.
Reproducing the Issue
I reproduced the problem with this code:
if __name__ == '__main__':
fn = 'writetest.txt'
fn2 = 'writetest_NoControlChars.txt'
# Create the problematic textfile
with open(fn, 'w') as wh:
wh.write("This line comes first!\n");
wh.write("Blah\x01\x1A\n"); # Write Start-of-Header and Subsitute unicode character to line
wh.write("This comes after!")
# Try to read the file above, removing the SOH/SUB characters if encountered
with open(fn, 'r') as rh:
with open(fn2, 'w') as wh:
for lineno, line in enumerate(rh):
sline = line.translate(None,'\x01\x1A')
wh.write(sline)
print "Line #{}: {}".format(lineno, sline)
print "Program executed."
Output
The code above creates 2 output files and produces the following in a console window:
Line #0: This line comes first!
Line #1: Blah
Program executed.
I step-debugged through the code in Eclipse and immediately after executing the
for lineno, line in enumerate(rh):
statement, rh, the handle for that opened file was closed. I had expected it to move onto the third line, printing out This comes after! to console and writing it out to writetest_NoControlChars.txt but neither events happened. Instead, execution jumped to print "Program executed".
Picture of Local Variable values in Debug Console
You have to open this file in binary mode if you know it contains non-text data: open(fn, 'rb')
I have a input.txt file with the following content.
3
4 5
I want to use this as a standard input by using the following command in the command line.
python a.py < input.txt
In the a.py script, I am trying to read the input line by line using input() function. I know there are better ways to read the stdin, but I need to use input() function.
A naive approach of
line1 = input()
line2 = input()
did not work. I get the following error message.
File "<string>", line 1
4 5
^
SyntaxError: unexpected EOF while parsing
That way is ok, it works:
read = input()
print(read)
but you are just reading one line.
From the input() doc:
The function then reads a line from input, converts it to a string
(stripping a trailing newline), and returns that.
That means that if the file does not end with a blank line, or what is the same, the last nonblank line of the file do not end with an end of line character, you will get exceptions.SyntaxError and the last line will not be read.
You mention HackerRank; looking at some of my old submissions, I think I opted to give up on input in lieu of sys.stdin manipulations. input() is very similar to next(sys.stdin), but the latter will handle EOF just fine.
By way of example, my answer for https://www.hackerrank.com/challenges/maximize-it/
import sys
import itertools
# next(sys.stdin) is functionally identical to input() here
nK, M = (int(n) for n in next(sys.stdin).split())
# but I can also iterate over it
K = [[int(n) for n in line.split()][1:] for line in sys.stdin]
print(max(sum(x**2 for x in combo) % M for combo in itertools.product(*K)))
I am trying to write a python script to execute a command line program with parameters imported from another file. The command line interface for the program works as follows:
./executable.x parameter(a) parameter(b) parameter(c) ...
My code is:
#program to pass parameters to softsusy
import subprocess
#open parameter file
f = open('test.dat', 'r')
program = './executable.x'
#select line from file and pass to program
for line in f:
subprocess.Popen([program, line])
The test.dat file looks like this:
param(a) param(b) param(c)...
The script calls the program however it does not pass the variables. What am I missing?
You want:
line=f.readline()
subprocess.Popen([program]+line.split())
What you currently have will pass the entire line to the program as a single argument. (like calling it in the shell as program "arg1 arg2 arg3"
Of course, if you want to call the program once for each line in the file:
with open('test.dat','r') as f:
for line in f:
#you could use shlex.split(line) as well -- that will preserve quotes, etc.
subprocess.Popen([program]+line.split())
To start with, for you case, use subprocess.call() not subprocess.popen()
As for the "params not being passed" there is nothing obviously wrong in your script. Try concatenating the whole thing into long string and giving the string to .call() instead of list.
subprocess.call( program + " " + " ".join(line) )
Are you sure that line contains the data you expect it to contain?
To make sure, (if source file is short) try turning the file into list explicitly and making sure there is data in "line":
for line in file.readlines():
if len(line.trim().split(" ")) < 2:
raise Exception("Where are my params?")
I'm trying to replace some text in a file with a value. Everything works fine but when I look at the file after its completed there is a new (blank) line after each line in the file. Is there something I can do to prevent this from happening.
Here is the code as I have it:
import fileinput
for line in fileinput.FileInput("testfile.txt",inplace=1):
line = line.replace("newhost",host)
print line
Thank you,
Aaron
Each line is read from the file with its ending newline, and the print adds one of its own.
You can:
print line,
Which won't add a newline after the line.
The print line automatically adds a newline. You'd best do a sys.stdout.write(line) instead.
print adds a new-line character:
A '\n' character is written at the end, unless the print statement ends with a comma. This is the only action if the statement contains just the keyword print.