I am trying to implement a decorator to retry a urllib2.urlopen n times.
I cannot get the decorator to work. When I run it I get the followin error:
Traceback (most recent call last):
File "F:\retry\dec_class.py", line 60, in
x.getURLdata('127.0.0.1')
TypeError: 'NoneType' object is not callable
Can anyone give me hand please?
import serial, urllib2, time
from functools import wraps
import xml.etree.cElementTree as ET
from xml.etree.cElementTree import parse
class Retry(object):
default_exceptions = (Exception)
def __init__(self, tries, exceptions=None, delay=0):
self.tries = tries
if exceptions is None:
exceptions = Retry.default_exceptions
self.exceptions = exceptions
self.delay = delay
def __call__(self, f):
def fn(*args, **kwargs):
tried = 0
exception = None
while tried <= self.tries:
try:
return f(*args, **kwargs)
except self.exceptions, e:
print "Retry, exception: "+str(e)
time.sleep(self.delay)
tried += 1
exception = e
#if no success after tries, raise last exception
raise exception
return fn
class getURL(object):
#Retry(2 )
def getURLdata(self, IPaddress):
try:
f = urllib2.urlopen(''.join(['http://', IPaddress]))
f = ET.parse(f)
return f
except IOError, err:
print("L112 IOError is %s" %err)
except urllib2.URLError, err:
print("L114 urllib2.URLError is %s" %err)
except urllib2.HTTPError, err:
print("L116 urllib2.HTTPError is %s" %err)
except Exception, err :
print("L118 Exception is %s" %err)
x = getURL()
x.getURLdata('127.0.0.1')
Your __call__ method doesn't return fn. Instead, it implicitly returns None and so None is bound to getURLdata.
Related
I'm developing a python bot and the debug sucks, when I use try catch to handle exceptions.
I need to get the right error line, when error occurs in a subfile, where I'm import a function. Following, is an example:
My files structure:
div.py
main.py
div.py:
def div(n):
return n / 0
main.py:
from div import div
import sys
try:
print(div(5))
except Exception as e:
exception_type, exception_object, exception_traceback = sys.exc_info()
filename = exception_traceback.tb_frame.f_code.co_filename
line_number = exception_traceback.tb_lineno
print("Exception type: ", exception_type)
print("File name: ", filename)
print("Line number: ", line_number) # return line 5
print("Error: ", e)
I was expecting get the line 2 in 'print("Line number: ", line_number)', because the error occurs in line 2 in div.py, but return line 5, where I call the function.
I search how get error lines in try catch, but I only find solutions like this, where return error line in main file, but not in subfile.
Here's an example extracting the last stack frame which gives what you want:
import traceback
from div import div
import sys
try:
print(div(5))
except Exception as e:
exception_type, exception_object, exception_traceback = sys.exc_info()
last_frame = traceback.extract_tb(exception_traceback)[-1]
print("Exception type: ", exception_type.__name__)
print("File name: ", last_frame.filename)
print("Line number: ", last_frame.lineno)
print("Error: ", e)
Output:
Exception type: ZeroDivisionError
File name: C:\Users\metolone\div.py
Line number: 2
Error: division by zero
You could also walk the frame formatting as you like:
import traceback
from div import div
import sys
try:
print(div(5))
except Exception as e:
exception_type, exception_object, exception_traceback = sys.exc_info()
tb = traceback.extract_tb(exception_traceback)
print("Exception type: ", exception_type.__name__)
print("Error: ", e)
for frame in tb:
print(f'File: {frame.filename}({frame.lineno}):\n {frame.line}')
Output:
Exception type: ZeroDivisionError
Error: division by zero
File: C:\Users\metolone\test.py(6):
print(div(5))
File: C:\Users\metolone\div.py(2):
return n / 0
I am using a thread pool to send requests in parallel (generate a list of urls, fetch in parallel, request all of the urls concurrently), parsing some data out of the response to a couple of dicts, cross-mapping keys across dicts and then writing it back to pandas.DataFrame
def fetch_point(point_url):
try:
r = requests.get(point_url, headers=self.headers)
r.raise_for_status()
except requests.exceptions.HTTPError as errh:
logging.error(f'HTTP Error: {errh}')
except requests.exceptions.ConnectionError as errc:
logging.error(f'Connection Error: {errc}')
except requests.exceptions.Timeout as errt:
logging.error(f'Timeout Error: {errt}')
except requests.exceptions.RequestException as e:
logging.error(e)
raise SystemExit(e)
result = r.json().get('data')
# print(result)
building_url = result['building']
return point_url, building_url
def fetch_building(building_url):
try:
r = requests.get(building_url, headers=self.headers)
r.raise_for_status()
except requests.exceptions.HTTPError as errh:
logging.error(f'HTTP Error: {errh}')
except requests.exceptions.ConnectionError as errc:
logging.error(f'Connection Error: {errc}')
except requests.exceptions.Timeout as errt:
logging.error(f'Timeout Error: {errt}')
except requests.exceptions.RequestException as e:
logging.error(e)
raise SystemExit(e)
result = r.json().get('data')
building_name = result['name']
return building_url, building_name
pool = ThreadPoolExecutor()
point_urls = df.loc[~df['Point Url'].isnull(), 'Point Url'].to_list()
building_urls = {}
for point_url, building_url in pool.map(fetch_point, point_urls):
building_urls[point_url] = building_url
building_urls_list = building_urls.values()
building_names = {}
for building_url, building_name in pool.map(fetch_building, building_urls_list):
building_names[building_url] = building_name
point_building_map = {k: building_names[building_urls[k]] for k in building_urls}
for key in point_building_map.keys():
df.loc[df['Point Url'] == key, 'Building'] = point_building_map[key]
I am wondering if there is a more optimized approach I could consider. Should I go for asyncio/aiohttp instead of ThreadPoolExecutor?
I am creating a flask application and whenever I am trying to raise a UnicodeDecodeError from the class Validation and returning to my main try block then instead of going to UnicodeDecodeError exception it's going to Exception block
This is my main block from where I am calling my class Validation and expecting a UnicodeDecodeError
try:
validation = Validation(request.files['csvfile'])
validation.checkextension()
# columns = validation.check_columns(csv)
return redirect(request.url)
except UnicodeDecodeError:
# return Response("Error : %s"% UnicodeDecodeError)
return "Please enter a .csv extension"
except Exception as e:
print("abc",repr(e))
# return Response("Error : %s"% Exception)
return "Exception"
This is my class from where i am raising the error:
class Validation:
def __init__(self,file):
self.file = file
self.location = "./uploads/" + str(file.filename)
def checkextension(self):
try:
self.file.save(os.path.join("uploads", self.file.filename))
data = pd.read_csv(self.location)
except UnicodeDecodeError:
os.remove("./uploads/" + str(self.file.filename))
raise UnicodeDecodeError
except Exception:
print(Exception)
raise Exception
Also When I am printing the statement in except Exception as e:
I am getting this output:
TypeError('function takes exactly 5 arguments (0 given)')
I am getting TypeError but I am raising UnicodeDecodeError
class Application(object):
def __init__(self, master):
self.master = master
Tk.report_callback_exception = self.show_error
def show_error(self, *args):
err = traceback.format_exception(*args)
messagebox.showerror('Title', f"{err[-1]}")
When an exception is raised I will have something like this:
If a create a simple Class Exception from Exception to easily pass description:
class Pingu_Exception(Exception):
pass
if i except a ZeroDivisionError and Raise my error(Pingu_Exception) from an imported python file
I can easily catch it
try:
x = 4 / 0
except ZeroDivisionError:
raise Pingu_Exception("Description")
The problem is when I try to catch imported Exception.
For example:
from requests.exceptions import ReadTimeout
class Woocommerce_api(object):
def __init__(self):
self.orders_endpoint = "orders/"
self.customers_endpoint = "customers/"
self.products_endpoint = "products/"
def __api_json(self, endpoint):
try:
wcapi = API(
url="https://www.xxxx.it",
consumer_key=self.consumer_key,
consumer_secret=self.consumer_secret,
wp_api=True,
version="wc/v1",
query_string_auth=True,
timeout=3
)
return wcapi
except requests.exceptions.ReadTimeout:
raise Pingu_Exception('"Timeout error\nIl server non risponde\nRiprova nuovamente')
This is what I catch:
but if a try to raise an requests.exceptions.ReadTimeout, in his same function, it will work:
def __api_json(self, endpoint):
try:
raise requests.exceptions.ReadTimeout
wcapi = API(
url="https://www.slow-sud.it",
consumer_key=self.consumer_key,
consumer_secret=self.consumer_secret,
wp_api=True,
version="wc/v1",
query_string_auth=True,
timeout=3
)
return wcapi
except requests.exceptions.ReadTimeout:
raise Pingu_Exception('"Timeout error\nIl server non risponde\nRiprova nuovamente')
return False
I am a decently new python coder and i wish to create a twitter bot in which everytime it retweets, it favourites the tweet as well. I am not exactly sure how to do that but when the bot searches, it sends out an error message of 'list index out of range'.
import tweepy, time, traceback
from tweepy.auth import OAuthHandler
from tweepy.streaming import StreamListener, Stream
ckey = ''
csecret = ''
atoken = ''
asecret = ''
auths = OAuthHandler(ckey, csecret)
auths.set_access_token(atoken, asecret)
api = tweepy.API(auths)
class listener(StreamListener):
def on_data(self, raw_data):
try:
tweet_text = raw_data.lower().split('"text":')[1].split('","source":"')[0].replace(",", "")
screen_name = raw_data.lower().split('"screen_name":"')[1].split('","location"')[0].replace(",", "")
tweet_cid = raw_data.split('"id:')[1].split('"id_str":')[0].replace(",", "")
#there is ment to be 4 spaces at tweet_text
accs = [''] # banned accounts screen name goes in here
words = ['hate' , 'derp' , 'racist' , 'evil' , 'keemstar' , 'mario' , 'kirby'] #banned words goes in here
if not any(acc in screen_name.lower() for acc in accs):
if not any(word in tweet_text.lower() for word in words):
fav(tweet_cid)
follow(screen_name)
retweet(tweet_cid)
tweet(myinput)
#call what u want to do here
#fav(tweet_cid)
#retweet(tweet_cid)
return True
except Exception as e:
print (str(e)) # prints the error message, if you dont want it to comment it out.
pass
def on_error(self, status_code):
try:
print( "error" + status_code)
except Exception as e:
print(str(e))
pass
def retweet(tweet_cid):
try:
api.retweet(tweet_cid)
time.sleep(random.randit(range(50,900)))
except Exception as e:
print(str(e))
pass
def follow(screen_name):
try:
api.create_friendship(screen_name)
time.sleep(random.randit(range(50,900)))
except Exception as e:
print(str(e))
pass
def fav(tweet_cid):
try:
api.create_favourite(tweet_cid)
time.sleep(random.randit(range(600,1100)))
except Exception as e:
print(str(e))
pass
def unfav(tweet_cid):
try:
api.destroy_tweet(tweet_cid)
time.sleep(random.randit(range(8000,9000)))
except Exception as e:
print(str(e))
pass
def tweet(myinput):
try:
api.update_status(myinput)
time.sleep(random.randit(range(1000,4000)))
except Exception as e:
print(str(e))
pass
# tags below
track_words = [""] #deleted all tags so easier to read
follow_acc = [] # all username converted to user ids
try:
twt = Stream(auths, listener())
twt.filter(track=track_words, follow = follow_acc)
except Exception as e:
print (str(e))
pass
Is this what you are asking for? It gives the stack trace of the exception.
import traceback
try:
s='hi'
s=s+1
except Exception as e:
print(traceback.format_exc())
Output:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
Hope this helps! :)