Could anybody advice me if there is any way to keep file pointer in the nested IF clause.
I have to parse the file, and based on its content, different code blocks should process the file.
I came up with nested IF loops.
The code:
import re
with open('smartctl.txt', 'r') as file:
line = file.readlines()
for x in line:
matchIP = re.search('Checking', x)
if matchIP:
print(x)
Match_Micron55 = re.search('Micron_5100', x)
Match_Intel = re.search('INTEL', x)
Match_Micron600 = re.search('Micron_M600', x)
Any_Micron = re.search('Micron', x)
if Match_Micron55:
print("here we have Micron55")
elif Match_Intel:
print("here we have Intel")
elif Match_Micron600:
print('here we have Micron 600')
mline = line
print("file is open")
check = ""
for y in mline:
if y == x:
check == True
continue
if y.startswith(' 1 Raw_Read_Error_Rate') and check == True:
print(y)
continue
if y.startswith(' 5 Reallocated_Sector_Ct') and check == True:
print(y)
continue
if y.startswith('173 Unknown_Attribute') and check == True:
print(y)
break
elif Any_Micron:
print('Here we have unsorted values')
As you can see I read the file as line.
Then I go with variable X through the file.
Then, when I fall in IF condition, I have to CONTINUE reading the file: that's keep the file pointer and continue reading exactly from the place I went into the IF loop. I use 2 loops here with X and Y variables (for x in line and for y in mline). Could you tell me please if I can continue reading the same file in the second(nested) If confidition?
The method seems to be non working. Apart from creating Y variable I have also tried using X in the nested IF clause but was not succeed. The x (line) variable seems to not keep its value on the second IF entry.
I suspect your problem lies in the following code:
line = file.readlines()
for x in line:
The fileread is returning a line from the file, the x in line is iterating through the line a character at a time. I bvelieve you should restructure your code as follows:
replace:
with open('smartctl.txt', 'r') as file:
line = file.readlines()
for x in line:
with:
with open('smartctl.txt', 'r') as file:
for x in file.readlines():
Related
I am trying to create a function that takes an open file as an argument, reads the integers in the file which are all on their own line, then creates a list of those integers. The function should stop reading the file when there is an empty line. This is what I am stuck on.
def load_ints(file):
lst = []
x = 1
while x == 1:
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
x = 2
x = 2
return lst
the file I am testing it with looks like this:
1
0
-12
53
1078
Should not be read by load_ints!
len(line.strip()) != 0:
is not working,
it currently gives me a ValueError: invalid literal for int() with base 10: 'Should'
You need to put a break after the x = 2
else:
x = 2
break
Otherwise, the for loop will keep iterating over the file. It has read the blank line, executed the else condition, then carried on processing lines. So it tries to process the 'Should...' line, and fails because 'Should...' is not an integer.
Also, I don't see why you have the while statement. The for loop should be enough to iterate over the file and process each line, and the break I've suggested will exit the loop when you hit the blank line.
Other answers already point out the issue: you have to stop parsing the integers when encoutering the blank line.
Here's a one-liner using itertools.takewhile, stopping when stripping the line yields an empty line & converting to integer:
import itertools
def load_ints(file):
return [int(x) for x in itertools.takewhile(str.strip,file)]
result:
[1, 0, -12, 53, 1078]
So itertools.takewhile iterates on the file lines, and applies strip on each line. If the result is an empty string, it stops the iteration. Otherwise it continues so the line is converted to integer and added to the list comprehension.
The less lines you're writing in those cases, the less bugs you'll create with auxiliary variables & states.
I think it is not necessary the while.
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst.append(load)
else:
break
return lst
When you read a file you get a generator. Instead of reading it all to memory we could use the while loop to feed us with 1 row at a time and break when condition is met (row is blank). This should be the most efficient solution.
data = """\
1
2
-10
1241
Empty line above"""
with open("test.txt","w") as f:
f.write(data)
with open("test.txt") as f:
data = []
while True:
row = next(f).strip()
try:
data.append(int(row))
# Break if ValueError is raised (for instance blank line or string)
except ValueError:
break
data
Returns:
[1, 2, -10, 1241]
If you want a compact solution we could use takewhile from itertools. But this won't handle any error.
from itertools import takewhile
with open("test.txt") as f:
data = list(map(int,takewhile(lambda x: x.strip(), f)))
If you want to stop reading the file when the line is empty, you have to break the for loop :
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
break
return lst
You can also use re module:
import re
def load_ints(my_file):
return list(map(int, re.findall('-?\d', my_file.read())))
I have a python script which print in a text file every prime.
I would like my script to pickup the list where it left off so basically take the contents of the last line as a variable.
Here is my current script:
def calc():
while True:
x = 245747
y = (100**100)**100
for n in range (x,y):
if all(n%i!=0 for i in range (2,n)):
a=[]
a.append(n)
fo = open('primes.txt', 'a+')
print(n)
print ("", file = fo)
print ((a), file = fo)
fo.close
s = input('To do another calculation input yes, to quit input anything else...')
if s == 'yes':
continue
else:
break
calc()
I would like the variable x to get as an input the last line of primes.txt
There should be on that last line "[245747]" if the greatest prime number is 245747.
How could I achieve that? Thanks!
You can do use readlines and get the last item of the list:
file = open("primes.txt", "r").readlines()
x = file[len(file)-1]
I think this should work.
You can just get rid of the 2 "[" and "]" with split or something similar.
I am writing this code to read a text file and then print the line number after each line here is my code
with open("newfile.txt") as f:
for line in f:
x=1
y=str(x)
print(line)
print(x)
x=x+1
f.close()
I should expect some thing like that
Line one
1
Line two
2
Line three
3
but instead I am getting
Line one
1
Line two
1
Line three
1
Why is that !?
You can just use enumerate() :
with open("newfile.txt") as f:
for num,line in enumerate(f,1):
print line,'\n',num
Also note that you don't need to close the file when you use the with statement. It will automatically does it for you.
And about the x variable in your code, you shouldn't initialized it in your loop, you need to put x=1 out of the loop.
Adding comments to your code will help you see why you always print out 1.
with open("newfile.txt") as f:
for line in f:
x=1 # x is now equal to 1
y=str(x) # x is still 1, y is now equal to '1'
print(line) # prints out the line
print(x) # 1 is printed
x=x+1 # you now add 1 to x, but don't do anything with this
# updated value, because in the next loop x is again
# initialised to 1
f.close()
The problem is that you are initializing x to 1 inside the loop and before the print statement.
try:
x = 1
with open("newfile.txt") as f:
for line in f:
y = str(x)
print(line)
print(x)
x += 1
The issue with the code would be the x=1 inside of the loop. By moving that outside and initializing that before you should get the result you want. For example:
x=1
with open("newfile.txt") as f:
for line in f:
y=str(x)
print(line)
print(x)
x=x+1
This should work
heres the code for context.
def processScores( file, score):
#opens file using with method, reads each line with a for loop. If content in line
#agrees with parameters in elif statements, executes code in if statment. Otherwise, ignores line
with open(file,'r') as f:
for line in f: #starts for loop for all if statements
line = line.strip()
if line.isdigit():
start = int(line)
score.initialScore(start)
print(line)#DEBUG TEST**** #checks if first line is a number if it is adds it to intial score
elif len(line) == 0:
print(line)#DEBUG TEST****
continue #if a line has nothing in it. skip it
elif line == 'o' or line == 'O':
amount = next(f)
print(line)#DEBUG TEST****
score.updateOne(amount) #if line contains single score marker, Takes content in next line and
#inserts it into updateOne
elif line == 'm'or line == 'M':
scoreList = next(f)
lst = []
for item in scoreList:
print(line)#DEBUG TEST****
lst.append(item)
score.updateMany(lst) # if line contains list score marker, creates scoreList variable and places the next line into that variable
# creates lst variable and sets it to an empty list
# goes through the next line with the for loop and appends each item in the next line to the empty list
# then inserts newly populated lst into updateMany
elif line == 'X':
print(line)#DEBUG TEST****
score.get(self)
score.average(self) # if line contains terminator marker. prints total score and the average of the scores.
# because the file was opened with the 'with' method. the file closes after
the idea that I am trying to is work with a file that looks like this:
50
O
30
O
40
M
10 20 30
o
5
m
1 2 3
X
if the code sees an 'O' or an 'o' then it needs to take the next line in the code and add it to a running score.. However the next line is a blank space... So I need to skip to the second line after the 'O' or 'o'.
I was thinking of doing an exception for this, but before I go down that road I wanna see if anyone might know of a better way.
If you want to move along f skipping whitespace-only items,
while True:
x = next(f).strip()
if x: break
will work, as will
for x in f:
x = x.strip()
if x: break
The difference is, what if there is no following non-all-space item in f. The former will exit with a StopIteration exception, the latter exit the for loop with no exception but x set to ''. Pick your poison (which exit form would you rather deal with) and code accordingly!
How about something like:
For line in lines:
if type(line) == 'int':
oneCount += line
elif type(line) == 'list':
manyCount.append(line)
elif type(line) == 'str' and line != 'x':
continue
elif type(line) == None:
continue
else:
print scores
A useful model to think about this problem is a state machine.
The code has 3 states:
Read command code.
Add single score (on "O").
Add multiple scores (on "M").
By keeping a variable with the current state, you can process the input without skipping ahead.
Now, empty lines appear to serve no purpose so you could just remove them all from the input like this:
...
non_empty_lines = (line for line in f if line.strip())
for line in non_empty_lines:
... do your thing ...
The generator expression will filter lines that are all spaces.
If for some reason you cannot use generator expressions, then do it inside the loop:
...
for line in f:
if not line.strip():
continue
...
I want to print out a specific line of text base on user input. So far I have this:
list = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt")
listo = list.read()
nlines = 0
x = raw_input()
x.lower()
x.capitalize()
if listo.find(x) != -1:
linesr = listo.index(x)
defines = list.readlines(linesr)
print defines
print linesr
else:
print "Nope!"
But when I tried it out, the line number was wrong and it didn't print out anything. This gave no error or anything so I don't know what's wrong.
How do you make a program that opens and reads a specific line of text from a text file based on user input?
A more pythonic approach would be this:
search = raw_input().lower().capitalize()
with open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt") as datafile:
for line in datafile:
if search in line:
print line
break
else:
print 'Line not found'
Open the file with with so it will be closed automatically .
Don't read the whole file into memory. Just iterate over the lines.
Find the text with in
First, don't use list as a variable name. You're shadowing the builtin function list.
data_file = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt")
Second, don't read the file with read(), read it with readlines() as you'd really prefer lines.
lines = data_file.readlines()
line_no = int(raw_input("Gimme a line number:"))
try:
print lines[line_no]
except IndexError:
print "Nope"
First problem: x.lower() and x.capitalize() do not change the string. There is no way to change a string in Python. You can only create new strings. x.lower() and x.capitalize() create new strings. If you want x to be a name for the new string, you need to do that yourself:
x = x.lower().capitalize()
Second problem: Once you have read in the entire file with listo = list.read(), you are at the end of the file. Attempting to read from the file again will not read any more, so defines = list.readlines(linesr) cannot read anything.
listo = list.read()
.After you do this.the list pointer to the file reached the end of file.So
list.readlines()
again will not work unless you do
list.seek(0)
to bring the pointer at the start of file again.
If you are giving text as input then the following way will be useful
list = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt")
listo = list.readlines()
nlines = 0
x = raw_input()
x.lower()
x.capitalize()
for sentences in listo:
if x in sentences:
print sentences
Here is a simple way to achieve what you desire (Assuming you want to print all the lines starting with the sting you provide as input):
datalist = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt")
listo = datalist.readlines()
nlines = 0
x = raw_input()
x = x.lower()
x = x.capitalize()
for y in list0:
if y.startswith(x):
print y
Here are some small things which you should have in mind:
Do not set list as a variable name as it is a builtin function
x.lower() or x.capitalize() doesn't change x. It just returns a modified version of the string. In order re-use the modified string, set it up as a variable and then use it.
list.readlines(linesr) gives the the number of bytes that have to be read from the file and NOT the line at the index linesr
list = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt")
listo = list.read()
lines = listo.split("\n")
nlines = 0
x = raw_input()
x.lower()
x.capitalize()
if len(lines)>int(x):
defines = lines[int(x)-1]
print x
print defines
else:
print "Nope!"
try this code.
First, it will print the line number that you enter from the shell,
after that it will print the specified line of the file.(e.g if x is 3, it will print the 3. line of the document)
Never use built_in_ function names as variable names.
file_1 = open("/Users/nicejojo12/Desktop/Python/DictionaryDefinitions.txt.txt")
listo = file_1.readlines()
line_number = raw_input()
for lines in range(len(listo)):
if int(line_number) == lines:
print listo[lines]
else:
print "enter a line number between 1 to ", len(listo)
break
If you're expecting line numbers as user_input, this will fetch you the respective line from file.