Try/Except - If Exception occurs, execution stops. while True creates endless loop - python

I'm brand new to Python, my apologies if this is a trivial question. Have been googling for hours unsuccessfully.
I have a code that takes latitudes/longitudes from an Excel file and returns addresses using an API.
If Excel cells contain wrong Lat/Longs, it returns IndexError. In that case it just stops execution even if the next row contains correct (geocodable) Lat/Longs. I tried using while True, but it just keeps writing the results excluding the part after Except.
E.g. Excel has the following columns/values:
Lat Long
38.872476 -77.062334
1 23.456789
38.873411 -77.060907
The 1st line has correct Lat/Long, the 2nd incorrect, the 3rd correct. In the output file it shows the address of the 1st row and says "N/A" for the 2nd row, but ignores the 3rd row and stops execution.
try:
for row in range(rows):
row+=1
latitude = float(sheet.row_values(row)[0])
longitude = float(sheet.row_values(row)[1])
reverse_geocode_result = gmaps.reverse_geocode((latitude, longitude))
out_file.write("(" + str(latitude) + ", " + str(longitude) + ") location: " + str(reverse_geocode_result[1]['formatted_address']) + "\n")
except IndexError:
out_file.write("N/A")
else:
out_file.write("(" + str(latitude) + ", " + str(longitude) + ") location: " + str(reverse_geocode_result[1]['formatted_address']) + "\n")
print "Done."

I think you want to stick your try inside your for loop.
for row in range(rows):
try:
# Get the values
except IndexError:
out_file.write("N/A")
else:
out_file.write(...)
print "Done."
That way if there is an error, you'll write "N/A", but then be able to continue to the next element in the range.

Related

Remove string from text file after print (python)

I have the following code that pulls a list from a txt file and then prints one line at a time. The problem I am having is that I want the code to remove that line from the txt file after it has printed it.
I have tried using a few different methods I found online but had no success on maiking it work.
Would any have any idea's on how to achive this?
import time
from time import sleep
import random
my_file=open('testlist.txt','r')
file_lines=my_file.readlines()
my_file.close()
for line in file_lines:
try:
sep = line.split(":")
select_list = ["test " + sep[0] + "? " + sep[1], "test " + sep[0] + "! " + sep[1], "test " + sep[0] + "? " + sep[1]]
print(random.choice(select_list))
sleep(1)
except Exception as e:
print(e)
Basically after the "print(random.choice(select_list))", we would want to delete "line" from "testlist.txt".
Let's go through some logic and see how to achieve the results you are expecting.
Humanly / Intuitively, the actions are
1. Read files line-by-line to memory
my_file=open('testlist.txt','r')
file_lines=my_file.readlines()
my_file.close()
It would be a better practice to consider using with context managers (it will automatically help you close the file one you are out of the indentation from the with scope, i.e.
with open('testlist.txt','r') as my_file:
file_lines = my_file.readlines()
2. For each line that is read, (a) split it by : character, (b) perform a few string operations and (c) randomly select one of the output from (2b), i.e
for line in file_lines:
sep = line.split(":")
select_list = ["test " + sep[0] + "? " + sep[1], "test " + sep[0] + "! " + sep[1], "test " + sep[0] + "? " + sep[1]]
print(random.choice(select_list))
2b. Now, lets take a look at (2b) and see what we are trying to achieve, i.e.
select_list = ["test " + sep[0] + "? " + sep[1], "test " + sep[0] + "! " + sep[1], "test " + sep[0] + "? " + sep[1]]
We produce 3 items in the select_list, where it seems the "test " + sep[0] + "? " + sep[1] has 2 occurence and the "test " + sep[0] + "! " + sep[1] is included once.
"test " + sep[0] + "? " + sep[1]
"test " + sep[0] + "! " + sep[1]
"test " + sep[0] + "? " + sep[1]
in any case, the select_list = [ ... ] is a valid line of code.
2c. Regarding the print(random.choice(select_list)) line, it doesn't affect any variables and it's just randomly choosing an item from the select_list
Going back to original question,
I want the code to remove that line from the txt file after it has printed it.
Q: Would this mean removing the line from the original file_lines in open('testlist.txt','r')?
A: If so, then it would be removing all lines from the original testlist.txt, because if everything would checks out for step 2b and 2c (in the try part of the code).
But if step 2b or 2c throws an error and get caught in the except, then it would be a line that you won't want to throw out (as per your original question).
In that case, it looks like what you want to get eventually is a list of lines that falls into the except scope of the code.
If so, then you would be looking at something like this:
# Reading the original file.
with open('testlist.txt','r') as my_file:
# Opening a file to write the lines that falls into the exception
with open('testlist-exceptions.txt', 'w') as fout:
# Iterate through the original file line by line.
for line in my_file:
# Step 2a.
sep = line.split(":")
# Supposedly step 2b, but since this is the only
# point of the code that can throw an exception
# most probably because there's no sep[1],
# you should instead check the length of the sep variable.
if len(sep) < 2: # i.e. does not have sep[1].
# Write to file.
fout.write(line)
else: # Otherwise, perform the step 2b.
select_list = ["test " + sep[0] + "? " + sep[1], "test " + sep[0] + "! " + sep[1], "test " + sep[0] + "? " + sep[1]]
print(random.choice(select_list))
Now the new logic is a lot simpler than the intuition based logic you have in the original code but achieves the same output that you are expecting.
The new logic is as such:
Open the original file for reading, open another file to write the file that I expect
Read the file line by line
Split the file by :
Check if it allows the string operation to join the sep[0] and sep[1]
if yes, perform the string operation to create select_list and choose one of the item in select_list to print to console
if no, print out that line to the output file.
If for some reason, you really want to work with the file in place with Python, then take a look at Is it possible to modify lines in a file in-place?
And if you really need to reduce memory footprint and want something that can edit lines of the file in-place, then you would have to dig a little into file seek function https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects
Some unsolicited Python suggestions (hope this helps)
When you need to delete something from file, if disk space allows, don't delete it, create another file with the expected output without the deleted lines.
Whenever possible, try to treat files that you want to read as immutable, and less like Perl-style in-place files that allows edits
It's tempting to do try-excepts when you just want something to work, but catch-all excepts are hard to debug and normally shows that the logic of the steps can be better. https://docs.python.org/3/tutorial/errors.html#handling-exceptions
I would give you example but better try to follow this guide there is various ways , first issue is opening the file with 'r' mode
Deleting lines

could not convert string to float "price"

when I run the program this has been popping up. could not convert string to float. I tried to look it up but I couldn't find anything.
here's the code:
f = open("ticket.txt",'r')
s=f.read()
lines=s.split("\n")
priceMax=0
priceMin=9999
total=0
for line in lines:
cols=line.split(" ")
price=(float)(cols[1])
total=total+price
if(price>priceMax):
priceMax=price
if(price<priceMin):
priceMin=price
f.close()
f=open("output.txt",'w')
f.write("*******************************************\n")
f.write(" TICKET REPORT\n")
f.write("*******************************************\n\n")
f.write("There are " + str(len(lines)) + " tickets in the database.\n\n")
f.write("Maximum Ticket price is $" + str(priceMax) + "\n")
f.write("Minimum Ticket price is $" + str(priceMin) + "\n")
f.write("Average Ticket price is $" + str(total / len(lines)) + "\n\n")
f.write("Thank you for using our ticket system!\n\n")
f.write("*******************************************\n")
f.close()
print("File Created sucessfully")
Yeah, indentation is important in Python. You must be consistent.
This "cast" (float) evaluates to, basically, the float() function, and then you call it, so that's not the problem. More canonical is f = float("123.45"). Now, this will throw a ValueError exception if there's an invalid number passed, so, you might want to catch this, so you can find out where the problem is. Along the lines of:
s = "123.baboom"
try:
f = float(s)
except ValueError as e:
print("Oh, no, got an exception:", e)
print("The offending string was: ", s)
What's the error that's shown?
I think the issue is that you have started the list with cols[1] instead of cols[0].
Also the indentation is wrong here.
for line in lines:
cols=line.split(" ")
price=(float)(cols[0])
total=total+price
if(price>priceMax):
priceMax=price
if(price<priceMin):
priceMin=price

Python strange "string indices must be integers" error

Problem solved! was newfilename[0,3] instead of newfilename[0: 3]
I know this question has been asked before and I have look around on all the answers and the types of problems people have been having related to this error message, but was unable to find anyone with the same type of problem.
I am sowing the whole method just in case. So here is my problem;
When I am trying to get is a substring of "newfilename" using newfilename[int, int] and the compiler keeps thinking I don't have an integer there when I do, at least from my checking I do.
What I'm doing with this code: I am cutting of the end of a filename such as 'foo.txt' to get 'foo' that is saved as newfilename. Then I am adding the number (converted to a string) to the end of it to get 'foo 1' and after that adding back the '.txt' to get the final result of 'foo 1.txt'. The problem occurs when I try to get the substring out and delete the last four characters of the filename to get just 'foo'. After that, I do another check to see if there is a file like that still in the folder and if so I do another set of cutting and pasting to add 1 to the previous file. To be honest, I have not tested of the while loop will work I just thought it should work technically, but my code does not reach that far because of this error lol.
My error:
File "C:/Users/Reaper/IdeaProjects/Curch Rec Managment/Setup.py", line 243, in moveFiles
print(newfilename[0, 3])
TypeError: string indices must be integers
NOTE this error is from when I tried to hard code the numbers it to see if it would work
Here is the current error with the hard code commented out:
newfilename = newfilename[0, int(newfilename.__len__() - 4)] + " 1.m4a"
TypeError: string indices must be integers
What I have tried: I have tried hard coding the numbers is by literally typing in newfilename[0, 7] and still got the same error. I have tried doing this in a separate python file and it seems to work there fine. Also, what is really confusing me is that it works in another part of my program just fine as shown here:
nyear = str(input("Enter new Year: "))
if nyear[0:2] != "20" or nyear.__len__() > 4:
print("Sorry incorrect year. Please try again")
So I have been at it for a while now trying to figure out what in the world is going on and can't get there. Decided I would sleep on it but would post the question just in case. If someone could point out what may be wrong that would be awesome! Or tell me the compilers are just being stupid, well I guess that will do as well.
My function code
def moveFiles(pathList, source, filenameList):
# moves files to new location
# counter keeps track of file name position in list
cnter = 0
for x in pathList:
filename = filenameList[cnter]
#print(x + "\\" + filename)
# new filename
if filename.find("PR") == 0:
newfilename = filename[3:filename.__len__()]
else:
newfilename = filename[2:filename.__len__()]
# checking if file exists and adding numbers to the end if it does
if os.path.isfile(x + "\\" + newfilename):
print("File Name exists!!")
# adding a 1 to the end
print(newfilename)
# PROBLEM ON NEXT TWO LINES, also prob. on any line with the following calls
print(newfilename[0, 3])
newfilename = newfilename[0, int(newfilename.__len__() - 4)] + " 1.m4a"
print("Adding 1:", newfilename)
# once again check if the file exists and adding 1 to the last number
while os.path.isfile(x + "\\" + newfilename):
# me testing if maybe i just can't have math operations withing the substring call
print("File exists again!!")
num = newfilename.__len__() - 6
num2 = newfilename.__len__() - 4
num3 = int(newfilename[num, num2])
num = newfilename.__len__() - 5
newfilename = newfilename[0, num] + str(num3 + 1)
print("Adding 1:", newfilename)
# moving file and deleting prefix
if not os.path.isdir(x):
os.makedirs(x)
os.rename(source + "\\" + filename, x + "\\" + newfilename)
cnter += 1
I think you need this:
print(newfilename[0:3])

Python, read and write file is cutting final output file to limited number of lines?

So I wrote a small script that will convert my g-code file commands by replacing "G01" to "G1" it is all working perfectly but these files are very big they can end up with more then 10 or 20k lines of code!
My problem is that file with all code converted ends up with 4715 lines but original file has 4817 lines. Funny thing is the for loop is going through all lines but only first 4715 are written(I checked that by simple a = a + 1 every time something is written to a file)!
Here is the code it is very simple!
import string
a = 0
b = 0
s = open("test.gcode","r+")
replaced = open("test_replaced.gcode","a")
for line in s.readlines():
if "G01" in line:
replaced.write(line.replace("G01", "G1" ))
print ("G01 ==> G1")
a = a + 1
elif "G00" in line:
replaced.write(line.replace("G00", "G0" ))
print ("G00 ==> G0")
a = a + 1
else:
replaced.write(line.replace("******", "**" ))
print ("***")
a = a + 1
b = b + 1
#replaced.write(line.replace("G01", "G1" ))
#replaced.write(line.replace("G00", "G0" ))
print ("Done! - " + str(a) + " number of operations done!")
print ("Loopcount: " + str(b))
s.close()
As pointed out in a comment to your question, you should probably replace your open() statements with with statements. So, your code would become.
...
with open("test.gcode","r+") as s:
with open("test_replaced.gcode","a") as replaced:
...
print ("Done! - " + str(a) + " number of operations done!")
print ("Loopcount: " + str(b))
Please note that there is no longer a close() at the end of the script because the context manager (with) closes the file already.
All you code dealing with the files needs to be within the with blocks.
You can find more information about context managers here.

Converting/concatenating integer to strying with python

I'm trying to read the last line from a text file. Each line starts with a number, so the next time something is inserted, the new number will be incremented by 1.
For example, this would be a typical file
1. Something here date
2. Something else here date
#next entry would be "3. something date"
If the file is blank I can enter an entry with no problem. However, when there are already entries I get the following error
LastItemNum = lineList[-1][0:1] +1 #finds the last item's number
TypeError: cannon concatenate 'str' and 'int objects
Here's my code for the function
def AddToDo(self):
FILE = open(ToDo.filename,"a+") #open file for appending and reading
FileLines = FILE.readlines() #read the lines in the file
if os.path.getsize("EnteredInfo.dat") == 0: #if there is nothing, set the number to 1
LastItemNum = "1"
else:
LastItemNum = FileLines[-1][0:1] + 1 #finds the last items number
FILE.writelines(LastItemNum + ". " + self.Info + " " + str(datetime.datetime.now()) + '\n')
FILE.close()
I tried to convert LastItemNum to a string but I get the same "cannot concatenate" error.
LastItemNum = int(lineList[-1][0:1]) +1
then you've to convert LastItemNum back to string before writing to file, using :
LastItemNum=str(LastItemNum) or instead of this you can use string formatting.

Categories

Resources