How to use both default arguments and asterisk (*) in a function definition - python

I'm trying to log some message into a text file, and may also log an error if there was one.
I want to log to multiple files, but only print once, and using the same function.
Current Implementation:
def log_and_sysout(log_file, message, e=''):
'''
Writes logs and outputs to terminal
Params:
log_file: File to log to
message: -
e: Error, if there is one
'''
sys.stdout.write(message)
with open(log_file, "a") as f:
f.write(message + str(e))
try:
# Logic
success_message = 'Translations: Success \n'
log_and_sysout(log_path_1, success_message)
log_and_sysout(log_path_2, success_message)
except Exception as e:
fail_message = 'Translations: Fail \n'
log_and_sysout(log_path_1, fail_message, e)
log_and_sysout(log_path_2, fail_message, e)
I want something like this:
def log_and_sysout(*log_files, message, e=''):
sys.stdout.write(message)
for file in log_files:
with open(file, "a") as f:
f.write(message + str(e))
try:
# Logic
success_message = 'Translations: Success \n'
log_and_sysout(log_path_1, log_path_2, success_message)
except Exception as e:
fail_message = 'Translations: Fail \n'
log_and_sysout(log_path_1, log_path_2, fail_message, e)

Your are almost there:
success_message = 'Translations: Success \n'
log_and_sysout(log_path_1, log_path_2, message=success_message)
However, I would suggest you to define your function like that to avoid the parameter assignment:
def log_and_sysout(message, e=‘’, *list_file)
Last but not least, you might consider the library ‘logging’ for what you are trying to do.

Edit:
It seems that the correct format is
def log_and_sysout(message, *log_files, e=''):
sys.stdout.write(message)
for file in log_files:
with open(file, "a") as f:
f.write(message + str(e))
log_and_sysout(message, log_path_1, log_path_2)

Related

Proper General Exception Handling after User-Defined Exception Handling

I logically want to connect a user defined exception with general exception handling. Firstly, it should be checked whether the user defined exception is triggered. If it is not triggered, but another exception occurs, I want to print the exception information by get_exception_info().
I have the following code:
class TestException(Exception):
pass
def get_exception_info():
try:
exception_type, exception_value, exception_traceback = sys.exc_info()
file_name, line_number, procedure_name, line_code = traceback.extract_tb(exception_traceback)[-1] #this line is properly indented in my file
exception_info = ''.join('[Time Stamp]: '
+ str(time.strftime('%d-%m-%Y %I:%M:%S %p'))
+ '' + '[File Name]: ' + str(file_name) + ' '
+ '[Procedure Name]: ' + str(procedure_name) + ' '
+ '[Error Message]: ' + str(exception_value) + ' '
+ '[Error Type]: ' + str(exception_type) + ' '
+ '[Line Number]: ' + str(line_number) + ' '
+ '[Line Code]: ' + str(line_code))
return exception_info
except:
pass
def test_func(x):
try:
if x > 0:
raise TestException('wrong')
elif x < 0:
raise TestException('right')
else:
pass
except TestException as e:
print(e)
except Exception:
exception_info = get_exception_info()
print(exception_info)
finally:
pass
test_func(a)
Theoretically, this would cause an Exception and it should print out the result of get_exception_info(). However I just get "NameError: name 'a' is not defined.
What am I doing wrong? And, more importantly probably, is this the right way to archieve my goal?
Thank you!
The error indicates that the value a which you are passing into test_func() is not defined.
Add a line defining a, e.g.:
# ...
a = "hello"
test_func(a)
EDIT:
For your code to work, you also need to import time, traceback, and sys. I would also suggest not catching exceptions inside get_exception_info(), as this may hide exceptions that you actually want to see, i.e.:
import time
import traceback
import sys
class TestException(Exception):
pass
def get_exception_info():
exception_type, exception_value, exception_traceback = sys.exc_info()
file_name, line_number, procedure_name, line_code = traceback.extract_tb(exception_traceback)[-1]
exception_info = ' '.join([
'[Time Stamp]:',
time.strftime('%d-%m-%Y %I:%M:%S %p'),
'[File Name]:',
file_name,
'[Procedure Name]:',
procedure_name,
'[Error Message]:',
str(exception_value),
'[Error Type]:',
str(exception_type),
'[Line Number]:',
str(line_number),
'[Line Code]:',
line_code,
])
return exception_info
# ...
EDIT II:
It sounds like the question revolves around how to catch an undefined variable (a in this case).
In that case, I would suggest adding a try-except block around the function call, e.g.:
try:
test_func(a)
except Exception:
exception_info = get_exception_info()
print(exception_info)
When a is undefined, this will generate something along the lines of:
[Time Stamp]: 13-06-2021 10:44:31 AM [File Name]: /path/to/sf_exc.py [Procedure Name]: <module> [Error Message]: name 'a' is not defined [Error Type]: <class 'NameError'> [Line Number]: 76 [Line Code]: test_func(a)
Comment
As a general remark, instead of manually formatting the error message, I would use Python's logging module which is powerful and gives a lot of flexibility when it comes to formatting different types of messages, using a custom Formatter. In particular, Formatter comes with methods that can be customised to treat exceptions and stack information.

Syntax error in module 'lambda_function': unindent does not match any outer indentation level (lambda_function.py, line 26)

Syntax error in module 'lambda_function': unindent does not match any outer indentation level (lambda_function.py, line 26)
from _future_ import print_function
import json
import boto3
import time
import urllib
print('loading function')
s3 = boto3.client('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key'])
try:
print("Using waiter to waiting for object to persist thru s3 service")
waiter = s3.get_waiter('object_exists')
waiter.wait(Bucket+bucket, Key=key)
response = s3.head_object(Bucket=bucket, Key=key)
print("CONTENT TYPE: " +response['ContentType'])
print("Etag: " + response['ETag'])
print("Content-Length: ", response['ContentLength'])
print("Keyname: "+key)
print("Deleting object" + key)
s3.delete_object(Bucket=bucket, Key=key)
return response['ContentType']
except Exception as e
print(e)
print('Error getting object{} from bucket {} . Make sure they exist'
'bucket is in same region as this is'
'function.' ,format(key, bucket))
raise e
Your indentation is incorrect, just like the exception says.
def lambda_handler(event, context):
# indented by 3 spaces
try:
...
# indented by 4 spaces ...
except Exception as e # NOTE: Missing `:`
...
Your code example is also missing a : at the end of the exception handler
Right here:
print("Content-Length: ", response['ContentLength'])
print("Keyname: "+key)
print("Deleting object" + key)
s3.delete_object(Bucket=bucket, Key=key)
return response['ContentType']
except Exception as e: #<---also add me, the colon :)
print(e)
print('Error getting object{} from bucket {} . Make sure they exist'
'bucket is in same region as this is'
'function.' ,format(key, bucket))
raise e
The indent of the stuff after the except needs to be moved back one space.

Python custom 404 response error

I wrote a hiscore checker for a game that I play, basically you enter a list of usernames into the .txt file & it outputs the results in found.txt.
However if the page responds a 404 it throws an error instead of returning output as " 0 " & continuing with the list.
Example of script,
#!/usr/bin/python
import urllib2
def get_total(username):
try:
req = urllib2.Request('http://services.runescape.com/m=hiscore/index_lite.ws?player=' + username)
res = urllib2.urlopen(req).read()
parts = res.split(',')
return parts[1]
except urllib2.HTTPError, e:
if e.code == 404:
return "0"
except:
return "err"
filename = "check.txt"
accs = []
handler = open(filename)
for entry in handler.read().split('\n'):
if "No Displayname" not in entry:
accs.append(entry)
handler.close()
for account in accs:
display_name = account.split(':')[len(account.split(':')) - 1]
total = get_total(display_name)
if "err" not in total:
rStr = account + ' - ' + total
handler = open('tried.txt', 'a')
handler.write(rStr + '\n')
handler.close()
if total != "0" and total != "49":
handler = open('found.txt', 'a')
handler.write(rStr + '\n')
handler.close()
print rStr
else:
print "Error searching"
accs.append(account)
print "Done"
HTTPERROR exception that doesn't seem to be working,
except urllib2.HTTPError, e:
if e.code == 404:
return "0"
except:
return "err"
Error response shown below.
Now I understand the error shown doesn't seem to be related to a response of 404, however this only occurs with users that return a 404 response from the request, any other request works fine. So I can assume the issue is within the 404 response exception.
I believe the issue may lay in the fact that the 404 is a custom page which you get redirected too?
so the original page is " example.com/index.php " but the 404 is " example.com/error.php "?
Not sure how to fix.
For testing purposes, format to use is,
ID:USER:DISPLAY
which is placed into check.txt
It seems that total can end up being None. In that case you can't check that it has 'err' in it. To fix the crash, try changing that line to:
if total is not None and "err" not in total:
To be more specific, get_total is returning None, which means that either
parts[1] is None or
except urllib2.HTTPError, e: is executed but e.code is not 404.
In the latter case None is returned as the exception is caught but you're only dealing with the very specific 404 case and ignoring other cases.

Python Exception Handling with in a loop

An exception occurs when my program can't find the element its looking for, I want to log the event within the CSV, Display a message the error occurred and continue. I have successfully logged the event in the CSV and display the message, Then my program jumps out of the loop and stops. How can I instruct python to continue. Please check out my code.
sites = ['TCF00670','TCF00671','TCF00672','TCF00674','TCF00675','TCF00676','TCF00677']`
with open('list4.csv','wb') as f:
writer = csv.writer(f)
try:
for s in sites:
adrs = "http://turnpikeshoes.com/shop/" + str(s)
driver = webdriver.PhantomJS()
driver.get(adrs)
time.sleep(5)
LongDsc = driver.find_element_by_class_name("productLongDescription").text
print "Working.." + str(s)
writer.writerows([[LongDsc]])
except:
writer.writerows(['Error'])
print ("Error Logged..")
pass
driver.quit()
print "Complete."
Just put the try/except block inside the loop. And there is no need in that pass statement at the end of the except block.
with open('list4.csv','wb') as f:
writer = csv.writer(f)
for s in sites:
try:
adrs = "http://turnpikeshoes.com/shop/" + str(s)
driver = webdriver.PhantomJS()
driver.get(adrs)
time.sleep(5)
LongDsc = driver.find_element_by_class_name("productLongDescription").text
print "Working.." + str(s)
writer.writerows([[LongDsc]])
except:
writer.writerows(['Error'])
print ("Error Logged..")
NOTE It's generally a bad practice to use except without a particular exception class, e.g. you should do except Exception:...

Checking condition while Exception handling in python

This is part of my code in python. I want to check the error message and if HTTPError() then I want to add the host to the file ok.txt. But it doesn't work. what is the problem here?
except urllib2.URLError, e:
print '%-15s\t%15r' % (url.strip(), e)
if e == 'HTTPError()':
OK.write('%-15s' % (url.strip()) + '\n')
OK.flush()
When I run whole script the output is something like this:
http://a.com HTTPError()
http://b.com URLError(timeout('timed out',),)
http://c.com URLError(timeout('timed out',),)
http://d.com URLError(error(111, 'Connection refused'),)
http://e.com 200
Use isinstance() to check whether or not your error is of type HTTPError:
except urllib2.URLError as e: # use the "as e" instead of the old style comma delimitation.
print '%-15s\t%15r' % (url.strip(), e)
if isinstance(e, HTTPError):
OK.write('%-15s' % (url.strip()) + '\n')
OK.flush()

Categories