getting None at the end of reading a text file - python

I'm trying to read a text file with a blank line at the end of it, and I need to put those lines into a list.
The text file looks something like this:
this is the first line
this is the second line
*
(* is indicating a blank line)
i read the textfile like this:
read_str = file.readlines()
print(read_str)
It gives me the list I want, which is good, but at the end it says "None". Like this:
['this is the first line\n', 'this is the second line\n']
None
Why is it giving me "None" at the end, and how can I fix this?

As Kevin pointed out, I think this is related to your print function printing (by side effect) and then returning None (as do all Python functions with no explicit return statement).
For instance:
>>> x = 3
>>> print(x)
3
>>> print(print(x))
3
None

The third line is blank? So the file ends with a newline then nothing else? That's exactly the output you've shown! If you want a third entry in the array, then add a space to the blank line in the file. Not sure why you'd want that though.
What are you trying to achieve with your code? Including the code you haven't shown us...

Seems like you have an error there. You must have omitted the final line in your text editor, because with the same input you've specified, it should output with the following behaviour.
with open("test.txt", "r") as f:
f.readlines()
Outputs:
['this is the first line\n', 'this is the second line\n', '\n']

Related

Evaluation of IF statement in Python

Please help me try to understand the evaluation of this script. It must be something simple I'm not understanding. I want to scan a text file and output lines with specific string value.
So for example my txt file will contain simple stuff:
beep
boop
bop
Hey
beep
boop
bop
and the script is looking for the line with "Hey" and trying to output that line
file_path = "C:\\downloads\\test.txt"
i = 0
file_in = open(file_path,"r+") # read & write
for lines in file_in.readlines():
i+=1
#if lines.rfind("this entity will be skipped..."):
if lines.find("Hey"):
print(i, lines)
file_in.close()
For some reason it outputs every line except the one it found a match on. How is this possible?
It's probably more straightforward to do if "Hey" in lines: instead of if lines.find("Hey"):. If you really want to use find(), you could do this: if lines.find("Hey") != -1:
While Daniel's answer is, of course, correct and should be accepted, I want to fuel my OCD and offer some improvements:
# use context managers to automatically release file handler
with open(file_path) as file_in:
# file objects are iterable, will return lines
# reading entire file in memory can crash if file is too big
# enumerate() is a more readable alternative to manual counters
for i, line in enumerate(file_in): # 'line' should be singular
if "Hey" in line: # same as Daniel
print(i, line)
.find(sub) returns an integer - the first index of sub if sub is found, and -1 if it is not.
When "Hey" is present, it is at the first index (0), so that is what .find() returns. Otherwise, "Hey" is not found, so .find() returns -1.
Since python treats all integers as True except 0, then the conditional evaluates to True when 0 is returned, i.e. when "Hey" is found.
Change your use of .find() to something which fulfills your if statement the way you want.

Last line in text file lacks newline; how to cope?

I am reading the lines of a file and storing them in an array.
The contents of the file are as follows -
hi
hello
bi
bello
I am writing a program to reverse the order of these words such that they are now written into a new file as
bello
bi
hello
hi
currently, I am reading the file using
file1 = open('example.txt','r')
s = file1.readlines()
when i examine the array 's', it looks like this -
['hi\n', 'hello\n', 'bi\n', 'bello']
now I was using s[::-1] to reverse the order, but that results in the output looking something like -
bellohi
hello
bi
presumably because 'bello' is not follow by \n in the array where it is stored.
I have tried to fix it by manipulating the last term like this
s[-1]=s[-1]+'\n'
on the surface, it works - but am I unknowingly printing out an extra line or something or adding trailing spaces? Is there a better way to do this? Also why does the last string in the array not have a '\n'
You can make the addition conditional:
if not s[-1].endswith('\n'):
s[-1] += '\n'
Or you can normalize by removing any trailing newline and then put one back:
s[-1] = s[-1].rstrip('\n') + '\n'
I'd go with the former, but you see both approaches.
See this answer for help to remove the \n from the list elements.
See this answer for help on how to reverse through a list.
This code will get you the list you want. Could be refactored better... but that can be a challenge for you.
s = ['hi\n', 'hello\n', 'bi\n', 'bello']
revList = list(reversed(s))
for i, e in enumerate(revList):
revList[i] = e.strip("\n")
if i < len(revList)-1:
revList[i] = e + "\n"
print(revList)
When Python reads the file, it will read line breaks as they are strings. So the last word in the first file does not have a new line under it, so that's why it doesn't have "\n" in the list.
When you use [i-1] you are going backwards through the list, but you are keeping the line breaks in order. If you work through your code bit by bit, you will see why you get the output you are getting. Remember that computers take things literally.

Replace words in list that later will be used in variable

I have a file which currently stores a string eeb39d3e-dd4f-11e8-acf7-a6389e8e7978
which I am trying to pass into as a variable to my subprocess command.
My current code looks like this
with open(logfilnavn, 'r') as t:
test = t.readlines()
print(test)
But this prints ['eeb39d3e-dd4f-11e8-acf7-a6389e8e7978\n'] and I don't want the part with ['\n'] to be passed into my command, so i'm trying to remove them by using replace.
with open(logfilnavn, 'r') as t:
test = t.readlines()
removestrings = test.replace('[', '').replace('[', '').replace('\\', '').replace("'", '').replace('n', '')
print(removestrings)
I get an exception value saying this so how can I replace these with nothing and store them as a string for my subprocess command?
'list' object has no attribute 'replace'
so how can I replace these with nothing and store them as a string for my subprocess command?
readline() returns a list. Try print(test[0].strip())
You can read the whole file and split lines using str.splitlines:
test = t.read().splitlines()
Your test variable is a list, because readlines() returns a list of all lines read.
Since you said the file only contains this one line, you probably wish to perform the replace on only the first line that you read:
removestrings = test[0].replace('[', '').replace('[', '').replace('\\', '').replace("'", '').replace('n', '')
Where you went wrong...
file.readlines() in python returns an array (collection or grouping of the same variable type) of the lines in the file -- arrays in python are called lists. you, here are treating the list as a string. you must first target the string inside it, then apply that string-only function.
In this case however, this would not work as you are trying to change the way the python interpretter has displayed it for one to understand.
Further information...
In code it would not be a string - we just can't easily understand the stack, heap and memory addresses easily. The example below would work for any number of lines (but it will only print the first element) you will need to change that and
this may be useful...
you could perhaps make the variables globally available (so that other parts of the program can read them
more useless stuff
before they go out of scope - the word used to mean the points at which the interpreter (what runs the program) believes the variable is useful - so that it can remove it from memory, or in much larger programs only worry about the locality of variables e.g. when using for loops i is used a lot without scope there would need to be a different name for each variable in the whole project. scopes however get specialised (meaning that if a scope contains the re-declaration of a variable this would fail as it is already seen as being one. an easy way to understand this might be to think of them being branches and the connections between the tips of branches. they don't touch along with their variables.
solution?
e.g:
with open(logfilenavn, 'r') as file:
lines = file.readlines() # creates a list
# an in-line for loop that goes through each item and takes off the last character: \n - the newline character
#this will work with any number of lines
strippedLines = [line[:-1] for line in lines]
#or
strippedLines = [line.replace('\n', '') for line in lines]
#you can now print the string stored within the list
print(strippedLines[0]) # this prints the first element in the list
I hope this helped!
You get the error because readlines returns a list object. Since you mentioned in the comment that there is just one line in the file, its better to use readline() instead,
line = "" # so you can use it as a variable outside `with` scope,
with open("logfilnavn", 'r') as t:
line = t.readline()
print(line)
# output,
eeb39d3e-dd4f-11e8-acf7-a6389e8e7978
readlines will return a list of lines, and you can't use replace with a list.
If you really want to use readlines, you should know that it doesn't remove the newline character from the end, you'll have to do it yourself.
lines = [line.rstrip('\n') for line in t.readlines()]
But still, after removing the newline character yourself from the end of each line, you'll have a list of lines. And from the question, it looks like, you only have one line, you can just access first line lines[0].
Or you can just leave out readlines, and just use read, it'll read all of the contents from the file. And then just do rstrip.
contents = t.read().rstrip('\n')

How to avoid the last comma while writing an integer array into a text file in python

I need to write an array of integers into a text file, but the formatted solution is adding the comma after each item and I'd like to avoid the last one.
The code looks like this:
with open(name, 'a+') as f:
line = ['FOO ', description, '|Bar|']
f.writelines(line)
f.writelines("%d," % item for item in values)
f.writelines('\n')
Each line starts with a small description of what the array to follow contains, and then a list of integers. New lines are added in the loop as they become available.
The output I get looks something like this:
FOO description|Bar|274,549,549,824,824,824,824,824,794,765,765,736,736,736,736,736,
And I would like to have it look like this, without the last comma:
FOO description|Bar|274,549,549,824,824,824,824,824,794,765,765,736,736,736,736,736
I was unable to find a solution that would work with the writelines() and I need to avoid lengthy processing in additional loops.
Use join:
f.writelines(",".join(map(str,values)))
Note that values is first mapped to a list of strings, instead of numbers, with map.
You can slice it with using below example.
It will always delete last character.
line = ['FOO ', description, '|Bar|']
line = line[:-1]
f.writelines(line)
Slicing is the best approach and works well for every situation atleast in your case.
f.writelines(line[:-1])
You can use print function here.
print(*values,sep=',',file=f)
If you are using python2 please import print function.
from __future__ import print_function

how to print missing line in python?

I am searching a particular line in a file.
If my required line is not present i want to print that line is missing in the file.
For example my file contains below lines:
list 0
list 7
list 2
list 5
Here is the I have written so far :
fo=open(filename,"r")
for i in range(0,6):
str="list"+str(i)
for line in fo.readlines():
if not str in line:
print "%s%s" %(str,"is missing in file"
please anyone help me
The first problem is that list+str(i) isn't going to work, unless you happen to have defined list = 'list ' somewhere earlier.
The second problem is that by naming your variable str, you're hiding the function str, which means you can't call that function the next time through the loop.
The third problem is that you only open the file once, but you call readlines() on it 7 times. After the first time, there are no more lines to read, so you'll get an empty list back. Just call it once, outside the loop, and store the value: lines = fo.readlines(). Or, alternatively, reopen the file each time through the loop, instead of just once.
The third problem is that you're going to print the output once for every line that doesn't, instead of just one if any line doesn't match. This one is the only part that's tricky, so I'll come back to it.
The fourth problem is that your print statement is missing a ).
Finally, you've tagged your question with both python-2.7 and python-3.x. I'll assume you weren't just trying to throw on every tag in the world in hopes that would get more viewers, and actually want your code to run under both 2.7 and 3.3. In that case, you can't use print as a statement; you have to use it as a function.
So, how do you say "if the string is not in any of the lines"? The easy way is with the any function:
if not any(s in line for line in lines):
If you can't understand that, you can get the same effect by writing out the loop explicitly, something like this:
found = False
for line in lines:
if s in line:
found = True
break
if not found:
There are a lot of other problems that you should fix (e.g., close the file—ideally by using a with statement; avoid readlines when possible; etc.), but no more that you need to fix. So, here's a minimally-edited working version:
fo=open(filename,"r")
lines = fo.readlines()
for i in range(0,6):
s='list '+str(i)
if not any(s in line for line in lines):
print("%s%s" %(s,"is missing in file"))
You should never name a variable str as str is a builtin type in Python. Also, you were attempting to concatenate list, a function and a type, and a string. Instead you want to concatenate the string 'list ' with the string representation of the numbers. You don't need to call readlines() where you did. Instead, read the file into a list early and iterate over that list.
fo=open(filename,"r").readlines()
for i in range(0,6):
s = 'list ' + str(i)
foundline = False
for line in fo:
if s in line:
foundline = True
break
if not foundline:
print "%s%s" % (s,"is missing in file")
with open(filename,'r') as infile:
inlines=infile.readlines()
for term in xrange(0,10):
line='list %d\n' % term
if line not in inlines:
print line,'is not in the file'
//nb, this matches the entire search string to the input line. I assume you mean this rather than to look for the search term inside the input line, becuase searching for 'line 1' inside the line would match against 'line 1', 'line 10', 'line 1000' etc..

Categories

Resources