Python Except Errors (multiple errors) - python

I am using python 3. I use database to lookup the country of IP, if the IP is not in the database, return None or AAA. After all process, show the return result (either a country name or None or AAA ) in a new column on the data frame, Specifically, I have three columns that are date time and IP in the data frame, I would like to add a new column "code1" that shows the country name or None of this IP.
I add error exception in the code, however, it doesn't work. The code and error message are as below. Can anyone help?
The following is the report when I add "from geoip2.errors import AddressNotFoundError" to my code. I guess it means when there is address not found in the database, it return nothing rather a "none" (see, there is a empty square brackets), therefore, when I use df['code1']=code1, it reports the number of value is not equal to the number of index. (I am not sure).
In fact,my aim is to add a column to my original data frame that report the country of each ip or none if it is not in the database. Is there any other way to do so instead of " df['code1']=code1 "? Any help will be appreciated. Thanks

Exceptions are just like any other object in Python. They have to be defined somewhere. In this case, AddressNotFoundError is not defined so the interpreter has no idea what it means.
It has to be imported:
from geoip2.errors import AddressNotFoundError
or
import geoip2.errors.AddressNotFoundError
See relevant part of geoip2 documentation.

You can just leave out the AddressNotFoundError and instead do
try:
response1 = reader.country(row1)
code1.append(response1.country.iso_code)
except:
response1 = None
but if you really want to just except the AddressNotFoundError then at the top do
import geoip.errors.AddressNotFoundError

Related

What data type single element extracted from entries attribute of Connection object represent in python?

I am not well versed at python at all. I was asked to review someone else's python script that uses search ldap entries. Btw - I can't reach out to original developer for some reason and before it is deployed + tested visual code checking is required. With that constraints in mind, allow me to proceed.
import ldap3
from ldap3 import Server,Connection, ALL
conn = Connection(....)
conn.search(....)
for entry in conn.entries:
if (len(entry['cn']) > 0):
....
name = entry['name']
if name:
user_name = str(name)
else:
user_name = "Bob"
First question is len(entry['cn']) > 0 I like to interpret it as checking the length of characters of returned cn value from ldap e.g. cn=bob,ou=people,ou=foocomany. I am pretty sure entry['cn'] is NOT string type but I don't know what data type it represents. Can you tell me what type it is?
My 2nd + 3rd questions are not directly related to the original question, but plz bear with me asking for them with grace.
My 2nd question is, if that assumption is correct, entry['cn'] should be converted to string type like str(entry['cn']). Then check its length?
My 3rd question is on if stmt. I like to interpret it as if name is not null or if name is not None in pythonic way. Did I interpret it correctly? If so I should replace it as if not (name is None) would work? I googled on it to get that stmt.
Given the context and code provided, it looks like this snippet is using the ldap3 library.
From the relevant documentation, conn.entries should be a list of Entry objects.
This means that entry['cn'] should be returning an Attribute. Doing a bit of source diving, this appears to just be a fancy list with writable flags. len(entry['cn']) > 0 ends up calling this method, which just returns the number of values that attribute has. It being greater than 0 just ensuring that the cn is, in fact, set.

Search in text file by date

I have code like this:
from datetime import datetime
from tabulate import tabulate
def search_projection_date():
projections = open('projections.txt','r').readlines()
date = input("Input projection date: ")
try:
date = date.strptime(date, "%d.%m.%Y.")
except:
print("Date input error!")
#search_projection_date()
for i in projections:
projections = i.strip("\n").split("|")
if date == projections[2]:
table = [['Code:',projections[0]],['Hall:',projections[1]],['Date:',projections[2]],['Start time:',projections[3]],['End time:', projections[4]],['Day(s):', projections[5]], ['Movie:', projections[6]], ['Price:', projections[7]]]
print (tabulate(table))
#break
else:
print("No projection on that date")
And text file like this:
0001|AAA|17.12.2017.|20:30|21:00|sunday|For a few dolars more|150
0002|BBB|17.12.2017.|19:30|21:15|saturday|March on the Drina|300
0003|GGG|19.12.2017.|18:00|19:00|tuesday|A fistful of Dolars|500
0004|GGG|16.12.2017.|21:15|00:00|sunday|The Good, the Bad and the Ugly|350
I try to search movie projections by date...
If there is a projection on the entered date it will find it and print the list, but before printing that list it will always print "Date input error" and after that list "No projection on that date". (if I put break in if statement it will print only the first found projection on entered day, withouth else statement, obvious)
Questions: How to print ONLY list of projections without "date input error" if date is correctly input.
How to print only "No projection on that date" if date is correct but there is no projection and how to ask user for input that until puts it correctly? In this way with recursion it will always throw exception and recursion search_projection_date() function.
There are a whole bunch of major problems with your code. As it happens, they showcase why some general advice we hear so often is actually good advice.
The line date = input("Input projection date: ") creates a string named date. input always returns a string. Strings in Python do not have a method called strptime. Which brings us to issue #2:
You should not catch generic exceptions. You were probably looking to trap a TypeError or ValueError in the except clause. However, you are getting an error that says AttributeError: 'str' object has no attribute 'strptime'. This is because you can't call methods that you want to exist but don't. Your except line should probably read something like except ValueError:.
Your except clause does nothing useful (beyond the problems listed above). If the string is not formatted correctly, you print a message but continue anyway. You probably want to use raise in the except clause to propagate the exception further. Luckily for you, you actually want the date to be a string, which brings us to issue #4:
Why are you attempting to convert the string to a date to begin with? You can not compare a date object and a string that you get from the file and ever expect them to be equal. You want to compare a string to a string. If you had some kind of validation in mind, that's fine, but use datetime.strptime and don't replace the original string; just raise an error if it doesn't convert properly.
The else clause in a for loop will execute whenever the loop terminates normally (i.e., without a break). Since you always iterate through all the lines, you will always trigger the else clause. You need to have another way to determine if you found matching items, like a boolean flag or a counter. I will show an example with a counter, since it is more general.
You never close your input file. Not a huge problem in this tiny example, but can cause major issues with bigger programs. Use a with block instead of raw open.
Your method of iterating through the file is not wrong per-se, but is inefficient. You load the entire file into memory, and then iterate over the lines. In Python, text files are already iterable over the lines, which is much more efficient since it only loads one line at a time into memory, and also doesn't make you process the file twice.
Combining all that, you can make your code look like this:
def search_projection_date():
counter = 0
with open('projections.txt','r') as projections:
date = input("Input projection date: ")
for line in projections:
projection = line.strip("\n").split("|")
if date == projection[2]:
table = [['Code:',projection[0]],
['Hall:',projection[1]],
['Date:',projection[2]],
['Start time:',projection[3]],
['End time:', projection[4]],
['Day(s):', projection[5]],
['Movie:', projection[6]],
['Price:', projection[7]]]
print(tabulate(table))
counter += 1
if not counter:
print("No projection on that date")
else:
print("Found {0} projections on {1}".format(counter, date))
I trusted your use of tabulate since I am not familiar with the module and have no intention of installing it. Keep in mind that the date verification is optional. If the user enters an invalid string, that's the end of it: you don't need to check for dates like 'aaaa' because they will just print No projection on that date. If you insist on keeping the verification, do it more like this:
from datetime import datetime
datetime.strftime(date, '%d.%m.%Y.')
That's it. It will raise a ValueError if the date does not match. You don't need to do anything with the result. If you want to change the error message, or return instead of raising an error, you can catch the exception:
try:
datetime.strftime(date, '%d.%m.%Y.')
except ValueError:
print('Bad date entered')
return
Notice that I am catching a very specific type of exception here, not using a generic except clause.

Infinite For Loop issue in Python

I need to extract an ID from a JSON string that is needed for loading information into a MySQL database. The ID is a 5 or 6 digit number, but the JSON key that contains this number is the URL net_devices resource string that has the number at the end like this example:
{u'router': u'https://www.somecompany.com/api/v2/routers/123456/'}
Since there is not a key with just the ID, I have used the following to return just the ID from the JSON key string:
url = 'https://www.somecompany.com/api/v2/net_devices/?fields=router,service_type'
r = json.loads(s.get((url), headers=headers).text)
status = r["data"]
for item in status:
type = item['service_type']
router_url = item['router']
router_id = router_url.replace("https://www.somecompany.com/api/v2/routers/", "")
id = router_id.replace("/", "")
print id
This does indeed return just the ID values I want, and it doesn't matter if the result varies in the number of digits.
The problem: This code creates an infinite loop when I include the two lines above the print statement.
How can I change the syntax to allow the loop to run through all the returned IDs once, but still strip out everything except the numerical ID?
I am new to Python, and just starting to write code again after a very long hiatus since college. Any help would be greatly appreciated!
UPDATE
Thanks everyone for the feedback! With the help from David and Gerrat, I was able to find the issue that was causing the infinite loop and it was not this segment of the code, but another segment that was not properly indented. I am learning how to properly indent loops in Python, and this was one of my silly mistakes! Thanks again for the help!

More simplified / efficient way to define variables when there are errors

I am just learning python and can't come up with a more efficient way to write a set of code. The code looks through the result of an API call and pulls out specific text into a cell (which eventually goes into Excel). When it can't find the specific text, it returns "NA" for that specific cell. The way I currently have it written is:
try:
company = 'company name in API output' #path to the value of the key that matches company name
except:
company:'NA' #Sometimes, the company name isn't in the API output and this results in an IndexError, so it should return 'NA' in the specific cell
try:
location = 'location of company in API output' #path to the value of the key that matches location
except:
location = 'NA'
# etc... This data eventually gets appended to a table row by row and then exported to pandas if that is helpful to know.
The code runs fine as is so I don't need help with that aspect. What I'd like input on is whether there is a better way to write the code, perhaps using a function or other python code so that I don't have to have try/excepts for every variable BUT written in a way so that even if one variable results in an error, not all variables become 'NA.' Thanks in advance for any help!

App Engine getRecord not returning content

In Google App Engine, I am trying to get a specific record and the content associated with it. I use the following (relevant) code (all necessary GData is imported and the client is authenticated):
sclient = gdata.spreadsheet.text_db.DatabaseClient(username, password)
gdata.alt.appengine.run_on_appengine(sclient)
gdata.alt.appengine.run_on_appengine(sclient._GetDocsClient())
gdata.alt.appengine.run_on_appengine(sclient._GetSpreadsheetsClient())
ss = sclient.GetDatabases(spreadsheet_key="0AqKqcvXam_kcdFlfckZfVzRiaVpRelp2T1FsVl9rRHc")
processedSheet = ss[0].GetTables(worksheet_id=1)
targetTotals = processedSheet[0].GetRecord(row_number=1)
total1 = targetTotals.content["votea"]
The problem is in the last line. It throws this error:
AttributeError: 'NoneType' object has no attribute 'content'
I looked in the source code for the GData spreadsheets text_db module and the return line says this:
return Record(content=None, row_entry=row_feed.entry[0],
Meaning that the function by design doesn't return the content? That doesn't make too much sense. Am I using the wrong function. What I'm trying to accomplish is to get the value of the cells in a row. My spreadsheet (that processedSheet is referring to) has column headers called "votea", "voteb", etc. The first row is integers. So, any ideas?
make sure you don't have any empty rows in spreadsheet. API will stop reading data when it encounters first empty line, so if your first row in spreadsheet is empty, you wont get any results.

Categories

Resources