Break program if file is empty - python

The code below picks a random word from a file and later delete the word and its working great. I want the program to BREAK when file is empty since I delete every random word picked from the file.
Here is Random part of the code:
import random
import os
g = r"C:\Users\Homer\name.txt"
lines = [line.rstrip('\n') for line in open(g)]
rand = random.choice(lines)
print(rand)
Is it good to say Break if file is empty and print "file is empty"?
Or if Random (rand) return no word, then break and print file is empty.
I have already checked this site and there are some answers on how to check if a file is empty and print file empty or file size is zero or there is not word in file. However, I could find one that say BREAK program if file is empty. I get the error below when my file is empty.
--->rand = random.choice(lines)
IndexError: Cannot choose from an empty sequence
At the moment I'm using the code below to check if file is empty or not. but i keep getting error with the break statement.
if os.path.getsize("name.txt") == 0:
print("File is Empty")
else:
print("File is not Empty")
break
----> SyntaxError: 'break' outside loop

What your code should be (I think):
if os.path.getsize("name.txt") == 0:
print("File is Empty")
else:
return print("File is not Empty")
You're nearly there.
break is used to prematurely stop a for loop. The default behaviour of a loop without explicit break keywords is continue until there are no indexes left in the iterator.
You're not using a loop here. So when you ask Python to break there is nothing for it to stop.
Example usage of break keyword:
for x in range(20):
if x != 13:
print(x)
continue # uneccesary as it will continue by default
else:
print("we don't like 13")
break

Related

Read files of a line in python

I have a 1000 files named coord_1.xvg, coord_2.xvg and so on. I have written a program that reads the second column of each of these files and gives me the output on the if else condition that I have provided. It prints a list of N's followed by either P or R depending on whichever is obtained first and stops.
from pathlib import Path
for file in Path("/home/abc/xyz/coord/").rglob("*.xvg"):
with file.open("r") as f:
for i, line in enumerate(file):
if i < 22:
continue
line = line.strip().split()
if float(line[1]) >= 9.5:
print("P")
break
elif float(line[1]) <= 5.9:
print("R")
break
else:
print("N")
I want to read these files and print the value in the first column corresponding to the output P or R as the output along with P or R. Basically, I need to find the line at which the reading of this file had stopped and extract the value corresponding to it.
Create a variable outside the loop, that you can set to i when your condition is met.
from pathlib import Path
stopped = 0
for file in Path("/home/abc/xyz/coord/").rglob("*.xvg"):
with file.open("r") as f:
for i, line in enumerate(file):
if i < 22:
continue
line = line.strip().split()
if float(line[1]) >= 9.5:
print("P")
stopped = i
break
elif float(line[1]) <= 5.9:
print("R")
stopped = i
break
else:
print("N")
Also, if I am understanding correctly, your break statements should be indented to be inside the if and elif blocks
Let me know if you have any questions.

if next(item) moves to the next item in a list, what is the eqvilant of next next(item) python

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
...

An if statement to check within try statement in Python, need the code to execute in case an exception is raised as well

I'm a bit stumped here. Here's a piece of Python code:
try:
if parse[index+1][0] != "5":
individual_services+=[individual_services_cur]
individual_services_cur=[]
except IndexError:
warning("Reached end of file. No next element")
individual_services+=[individual_services_cur]
individual_services_cur=[]
Basically I want these two actions (addition of individual_services_cur list to individual_services list and clearing of individual_services_cur list) to take place either if the next element in parse is not "5" or if it doesn't exist (basically it is the end of file).
I am wondering if there is a more elegant (maybe even, as they say, "pythonic") way to write this code, for example, without the need to write these two actions twice. I couldn't think of any good solution with finally or else statements, and it seems that I cannot get rid of try statement because once the end of file is reached, the IndexError exception is inevitably raised.
You can use an intermediate variable to perform the checks you need.
try:
value_to_check = parse[index+1][0]
except IndexError:
warning("Reached end of file. No next element")
value_to_check = None
finally:
if value_to_check != "5":
individual_services+=[individual_services_cur]
individual_services_cur=[]
Another idea:
update_i_s = True
try:
update_i_s= parse[index+1][0] != "5"
except IndexError:
warning("Reached end of file. No next element")
finally:
if update_i_s:
individual_services.append([individual_services_cur]) if flag
individual_services_cur=[]
flag=True is only needed for the case that there is only one line in the file, and only needs to be set once at the beginning (so don't go putting it inside any loops).
EDIT:
By the way, if there is a possibility the finally block could fail, you might want to do something like this:
try:
try:
update_i_s= parse[index+1][0] != "5"
except IndexError:
warning("Reached end of file. No next element")
finally:
if update_i_s:
individual_services.append([individual_services_cur]) if flag
individual_services_cur=[]
except Exception:
warning("failed to update individual_services")
raise
You could assign a variable in both cases and then check it once.
badstuff = False
try:
if parse[index+1][0] != "5":
badstuff = True
except IndexError:
warning("Reached end of file. No next element")
badstuff = True
if badstuff:
individual_services+=[individual_services_cur]
individual_services_cur=[]
If it suits you, you could put the if badstuff: in a finally block, depending on what the rest of your code is doing.
Alternatively, put the individual_services stuff in a function, and call it in both places.
How about
last = len(parse) - 1
if index == last or parse[index + 1][0] != "5":
individual_services.append(individual_services_cur)
individual_services_cur = []
Or thinking outside the box a bit:
if index + 1 not in (index for index, value in enumerate(parse) if value[0] == '5'):
individual_services+=[individual_services_cur]
individual_services_cur=[]
Where (index for index, value in enumerate(parse) if value[0] == '5') is a generator that yields the line number of each line that has a '5' as the first character. It is equivalent to this:
def has_5s(p):
'''Yield line numbers that begin with a 5'''
for index, line in enumerate(p):
yield index if line[0] == '5'
if index + 1 not in has_5s(parse):
individual_services+=[individual_services_cur]
individual_services_cur=[]
You are simply checking to see if the following line number (line + 1) is one of these line numbers yielded by the generator. Since enumerate and the generator itself are lazy this should be very fast.

Reading a file until a match found with python

I have been trying this code to loop through randomly until a match found in the lookin.txt file and stop when a match is found with no success as my Python knowledge not that brilliant. Code is working only once but i need it to run continously until it finds a match. I appreciate if someone can direct me in the right direction.
#! /usr/bin/env python
import random
randrange = random.SystemRandom().randrange
z = randrange( 1, 1000)
target_f = open("lookin.txt", 'rb')
read_f = target_f.read()
if z in read_f:
file = open('found.txt', 'ab')
file.write(z)
print "Found ",z
else:
print "Not found ",z
Lookin.txt:
453
7
8
56
78
332
you need to use while and change the random number:
#!/usr/bin/env python
import random
target_f = open("lookin.txt", 'rb')
read_f = target_f.read()
while True: # you need while loop here for looping
randrange = random.SystemRandom().randrange
z = str(randrange( 1, 1000))
if z in read_f:
file = open('found.txt', 'ab')
file.write(z)
file.close()
print "Found ",z
break # you can break or do some other stuff
else:
print "Not found ",z
import random
running=True
while running:
a=random.randint(1,1000)
with open ("lookin.txt") as f:
rl=f.readlines()
for i in rl:
if int(i)==a:
print ("Match found")
with open("found.txt","w") as t:
t.write(str(a))
running=False
Try this.Also with open method is better for file processes. If you want to only one random number, than you can just put the a variable outside of while loop.
The "z = randrange(1,1000)" gives you one random number and the rest of your script reads the entire file and tries to match that number against the file.
Instead, enclose place the script into a loop for it to keep trying.
import random
randrange = random.SystemRandom().randrange
while True:
z = randrange( 1, 1000)
DO YOUR SEARCH HERE
The while True will cause your script to run forever so depending on what you are trying to accomplish, you'll need to add an "exit()" someplace for when you want the program to end.
Also, your "if z in read_f" line fails because it expects a string and not the integer value from the random number generator. Try "if str(z) in read_f:"
We can get only integer value from target file(used with statement to read file) and create dictionary which get constant time for key search.
Apply while loop to find random number into file i.e. in created dictionary.
If random number found in the dictionary then add to found.txt and break code.
If not found random number then continue for next random number.
import random
randrange = random.SystemRandom().randrange
with open("lookin.txt", 'rb') as target_f:
tmp = [int(i.strip()) for i in target_f.read().split('\n') if i.isdigit() ]
no_dict = dict(zip(tmp, tmp))
while 1:
z = randrange( 1, 1000)
if z in no_dict:
with open('found.txt', 'ab') as target_f:
target_f.write("\n"+str(z))
print "Found ",z
break
else:
print "Not found ",z
Note: If target file not contains any integer in between random number range then code will go into infinite loop.

python read files and stop when a condition satisfies

I am trying a program where it reads all files in a directory and when the 'color=brown' is attained then my program has to stop reading even if finds 'color=brown' in the next file.I mean,the condition first met should only be taken.
I tried a program where it prints all the color=brown from all the files,but i have to stop after its first read. Please help!
import os
path = r'C:\Python27'
data = {}
for dir_entry in os.listdir(path):
dir_entry_path = os.path.join(path, dir_entry)
if os.path.isfile(dir_entry_path):
with open(dir_entry_path, 'r') as my_file:
for line in my_file:
for part in line.split():
if "color=brown" in part:
print part
please help!answers will be appreciated!
you can set a variable stating that you are done and then break out of each loop
but depending on the nesting of the loop it might be cleaner to use an exception to jump out of the loop (kind of like a goto in C):
try:
for m in range(10):
for n in range(10):
if m == 5 and n == 15:
raise StopIteration
except StopIteration:
print "found"
else:
print "not found"
print "always runs unless the other clauses return"
You're looking for the break statement.
...
if "color=brown" in part:
print part
# set some variable to check at the last thing before your other for loops
# turnover.
br = True
break
and then use that to break out of every other two for loops you've initiated.
if br == True:
break
else:
pass
if br == True:
break
else:
pass

Categories

Resources