How can I catch an error without using try/except? - python-3.x

Is there something that I could use to catch errors in python without using a try/except?
I'm thinking of something like this:
main.py
from catch_errors import catch_NameError
print(this_variable_is_not_defined)
catch_errors.py
def catch_NameError(error):
if type(error) == NameError:
print("You didn't define the error")
The output would be:
You didn't define the error
Instead of:
Traceback (most recent call last):
File "main.py", line 1, in <module>
print(this_variable_is_not_defined)
NameError: name 'this_variable_is_not_defined' is not defined

It can be done by creating a context manager, but it gives questionable benefit over an explicit try:except:. You will have to use the with statement, so it will be clear where behavior will change. In this example, I am using contextlib.contextmanager to do this, which saves the tedium of creating a class with __enter__ and __exit__ methods.
from contextlib import contextmanager
#contextmanager
def IgnoreNameErrorExceptions():
"""Context manager to ignore NameErrors."""
try:
yield
except NameError as e:
print(e) # You can print whatever you want here.
with IgnoreNameErrorExceptions():
print(this_variable_is_not_defined)
This will output
name 'this_variable_is_not_defined' is not defined

Related

Problem with traversing the same module second time

I have two .py files. The main_module is 'TS_File_analysis.py' and sub_module is 'Port_operations.py'.
Import sub_module in main_module.
from Port_operations import *
def main_menu():
try:
if r == 1:
print()
elif r == 2:
search_cmd_output()
elif r == 3:
port_analyze_drops()
elif r == 4:
print('Exit out.! Good bye..:)')
return
else:
print('Entered option was not valid.\n')
main_menu()
except ValueError as ex:
print('Din\'t choose any option.\n')
main_menu()
Import main_module in sub_module file.
from TS_File_analysis import main_menu
def port_analyze_drops():
try:
if int(r2) == 1:
get_output_of_port_drops()
elif int(r2) == 2:
get_output_of_port_errors()
elif int(r2) == 3:
del_res_file(temp_result2)
main_menu()
else:
print('Entered option was not valid.\n')
port_analyze_drops()
except ValueError as ex:
print('Din\'t choose any option.\n')
port_analyze_drops()
return
With the initial run, we can go from main_module to sub_module successfully and come back to main_module. Again if I want to go from main_module to sub_module it fails with the below traces.
Traceback (most recent call last):
File "C:\Users\user1\Documents\Python\Source\Workspace\TS_File_Analysis\TS_File_analysis.py", line 151, in <module>
main_menu()
File "C:\Users\user1\Documents\Python\Source\Workspace\TS_File_Analysis\TS_File_analysis.py", line 95, in main_menu
port_analyze_drops()
File "C:\Users\user1\Documents\Python\Source\Workspace\TS_File_Analysis\Port_operations.py", line 20, in port_analyze_drops
main_menu()
File "C:\Users\user1\Documents\Python\Source\Workspace\TS_File_Analysis\TS_File_analysis.py", line 94, in main_menu
port_analyze_drops.__module__
NameError: name 'port_analyze_drops' is not defined
Expectation is to switch from main_module to sub_module and vice versa as many times as you try to switch.
From the code snippets provided it is hard to see the module hierarchy, import structure, calling tree, and namespace. I would have to see the main_menu module to understand the import structure. If you can post that it would be helpful.
I can see two potential problems that may be confusing you.
First of all Python "import STAR" statements with 'import *' are totally frowned upon. It is considered poor namespace management practice, because you can easily clobber other object names without realizing it. It looks like you may be clobbering the main_menu function with your IMPORT STAR. Please provide the full source code for the 'TS_File_analysis.py' file.
Second, it is better to structure your modules with a top-level main module e.g., "app_main.py" that imports the other supporting modules. Your main_menu() function should be at the bottom of the app_main.py file and be run after the other modules are imported into it, not the other way around. Submodules should not be importing the main module.

How to get the actual file name in exception message in Databricks?

I am trying to figure out, how to get the actual file/module name in exception message in Databricks.
import traceback
def bad():
print("hello")
a = 1/0
def main():
try:
bad()
except Exception as e:
print(traceback.format_exc())
main()
When I run this the exception message I get like -
hello
Traceback (most recent call last):
File "<command-162594828857243>", line 8, in main
bad()
File "<command-162594828857243>", line 4, in bad
a = 1/0
ZeroDivisionError: division by zero
The "<command-162594828857243>" doesn't help at the time of debugging. I want the actual file/module name there.

Prevent custom assert from showing in traceback of python unittest

I'd like to add some custom assert methods to a TestCase. As a simple example, I've just put one inside the test class below. It works as expected, but when the output is generated the traceback includes the custom assert in the output.
What is the step necessary to make it behave like assertEqual()? The code for assertEqual is in TestCase, but the actual line that raises the assertion does not appear in the traceback. What do I need to do to make test_something2's output look more like test_something1's?
import unittest
class TestCustomAssert(unittest.TestCase):
def assertSomething(self, s):
self.assertEqual(s, 'something')
def test_something1(self):
self.assertEqual('foo', 'something')
def test_something2(self):
self.assertSomething('foo')
if __name__ == '__main__':
unittest.main()
Output
python3 custom_assert.py
FF
======================================================================
FAIL: test_something1 (__main__.TestCustomAssert)
----------------------------------------------------------------------
Traceback (most recent call last):
File "custom_assert.py", line 8, in test_something1
self.assertEqual('foo', 'something')
AssertionError: 'foo' != 'something'
- foo
+ something
======================================================================
FAIL: test_something2 (__main__.TestCustomAssert)
----------------------------------------------------------------------
Traceback (most recent call last):
File "custom_assert.py", line 10, in test_something2
self.assertSomething('foo')
File "custom_assert.py", line 6, in assertSomething
self.assertEqual(s, 'something')
AssertionError: 'foo' != 'something'
- foo
+ something
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=2)
unittest doesn't print tracebacks from frames that have __unittest=True in their globals.
From unittest.result:
def _is_relevant_tb_level(self, tb):
return '__unittest' in tb.tb_frame.f_globals
So, if you make a helper module, you can emulate that behavior:
helper.py:
__unittest = True
def assert_stuff(s):
assert s == 'something', "%s is not something" % s
Now you can call this helper from your test case.
I guess that one could make a very neat decorator that make such magic more automatic without a helper module but IMHO you shouldn't make effort to reduce the traceback anyway.

Python cmd shell: handling undefined commands

I'm writing a shell that must be able to take an unlimited number of commands. I can't figure out from the docs (https://docs.python.org/3.6/library/cmd.html) which say:
Cmd.default(line) Method called on an input line when the command
prefix is not recognized. If this method is not overridden, it prints
an error message and returns.
I must be writing the default() method incorrectly?
I've tried this:
import cmd
class MyShell(cmd.Cmd):
def default():
print('you entered this unknown command: ')
if __name__ == '__main__':
MyShell().cmdloop()
but get this (when I enter 'hi' in the shell):
(Cmd) hi
Traceback (most recent call last):
File "/Users/david/anaconda/lib/python3.6/cmd.py", line 214, in onecmd
func = getattr(self, 'do_' + cmd)
AttributeError: 'MyShell' object has no attribute 'do_hi'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "bitmessage_shell.py", line 9, in <module>
MyShell().cmdloop()
File "/Users/david/anaconda/lib/python3.6/cmd.py", line 138, in cmdloop
stop = self.onecmd(line)
File "/Users/david/anaconda/lib/python3.6/cmd.py", line 216, in onecmd
return self.default(line)
TypeError: default() takes 0 positional arguments but 2 were given
def default():
print('you entered this unknown command: ')
that doesn't work in a class. You need at least the object argument (self), or make the method static/class using #staticmethod or #classmethod decorators (but not very convenient, you may need the object state at some point)
Moreover, the parent class seems to pass the line, so now you need 2 arguments:
def default(self,line):
print('you entered this unknown command: ',line)

calling a tcl proc in python3

I am trying to call a tcl proc in a python program.
The tcl script starts with
proc scale_wigner-seitz_radii { } {
(I am not sure if I can put the full proc here, as this is a part of a licensed program).
This program is called by my python script:
#!/usr/bin/python3
import sys
from numpy import arange
from tempfile import mkstemp
from shutil import move, copy
from os import remove, close, mkdir, path
import Tkinter
def repll(file_path, pattern, subst):
print(pattern)
print(subst)
print(file_path)
r = Tkinter.Tk
# fullpath = str(subst) + "/" + file_path
fh, abs_path = mkstemp()
with open(abs_path, "w") as new_file:
with open(file_path, "r") as old_file:
for line in old_file:
new_file.write(line.replace(pattern.strip(),
str(subst).strip()))
r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
r.tk.eval('proc scale_wigner-seitz_radii')
copy(abs_path, path.join(str(subst), file_path))
inpf = str(sys.argv[1])
a = []
print (inpf)
with open(inpf, "r") as ifile:
for line in ifile:
if line.startswith("lattice parameter A"):
a = next(ifile, "")
print(a)
for i in arange(float(a)-.10, float(a)+.10, 0.02):
if not path.exists(str(i)):
mkdir(str(i))
repll(inpf, a, i)
I havn't make a minimal example, because this seems better than explaining in english.
At the very end of def repll, it is calling the tcl proc. I have never encountered a tcl script before, and found the calling process from this question.
But when I am running this, I am getting error:
Traceback (most recent call last):
File "xband.py", line 41, in <module>
repll(inpf, a, i)
File "xband.py", line 24, in repll
r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'
How I can solve this?
After Donal's Comment Thanks for your reply. After following your suggestion, I got same error from source line.
Traceback (most recent call last):
File "xband.py", line 41, in <module>
repll(inpf, a, i)
File "xband.py", line 24, in repll
r.tk.eval('/home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'
Sorry if its silly, but since the tcl is in different file, I must source that first, right? And, as I said, this is the first tcl code I am looking at, please be elaborate.
The problem seems to be this line:
r = Tkinter.Tk
My guess is, you think this is creating an instance of Tk, but you're merely saving a reference to the class rather than creating an instance of the class. When you instantiate it, the object that gets returned has an attribute named tk, which the object internally uses to reference the tcl interpreter. Since you aren't instantiating it, r (which points to Tk) has no such attribute.
To fix it, instantiate the class by adding parenthesis:
r = Tkinter.Tk()
r will now be a proper reference to a Tk object, and should have a tk attribute, and with that you can call eval on raw tcl code.

Resources