Can't use class constructor argument in Python - python

I can't get what I'm doing wrong here. I'm defining a class with the following code:
import sqlite3 as lite
import sys
import os.path
class database:
def __init__(self,dbfname):
if os.path.isfile(dbfname):
self.con = lite.connect(dbfname)
else:
self.con = self.createDBfile(dbfname)
#Other methods...
Then, when I try to make an instance of the class
base = database("mydb.db")
I get an error saying that there is no "global" variable named dbfname .
Traceback (most recent call last):
File "testdb.py", line 67, in <module>
base = database("mydb.db")
File "testdb.py", line 13, in __init__
self.con = self.createDBfile(dbfname)
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
NameError: global name 'dbfname' is not defined
What would be the correct way to use the argument variable dbfname ?

This code looks fine. The error isn't in the code you posted though; it's in testdb.py on line 15 in the createDBfile() method (not in the __init__()).
How do I know this? Well, lets carefully look at the traceback Python gives us:
Traceback (most recent call last):
File "testdb.py", line 67, in <module>
base = database("mydb.db")
File "testdb.py", line 13, in __init__
self.con = self.createDBfile(dbfname)
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
NameError: global name 'dbfname' is not defined
Like the first line says, the most recent call is last. So you read a traceback from down to up (and not from up to down).
The very last line is the actual error, but just before that is:
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
So it says that in the file testdb.py, on line 15, in the method createDBfile() an error occurred. Python also prints out the contents of this line 15.
Above that is the call to the createDBfile() method in your __init__() function, and above that the call to the __init__() function (by creating the class instance).
You didn't post the contents of this createDBfile() method, so I can't tell you where exactly the error is. I suspect you did something wrong with the function arguments (perhaps as simple as a typo?)

Related

using Textatistic: OSError: Cannot load hyphen dictionary

I am trying to use Textatistic. However it curs a error and I have am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.
The source code is
from pathlib import Path
import textatistic
text = Path('Robinson Crusoe.txt').read_text(encoding='utf-8')
readability = textatistic.Textatistic(text)
print(readability.dict())
Traceback (most recent call last):
File "D:\anaconda3\lib\site-packages\hyphen\hyphenator.py", line 60, in __init__
self.__hyphenate__ = hnj.hyphenator_(file_path,
OSError: Cannot load hyphen dictionary.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\Demos\python_demo\main.py", line 2, in <module>
import textatistic
File "D:\anaconda3\lib\site-packages\textatistic\__init__.py", line 27, in <module>
from .textatistic import *
File "D:\anaconda3\lib\site-packages\textatistic\textatistic.py", line 39, in <module>
class Textatistic(object):
File "D:\anaconda3\lib\site-packages\textatistic\textatistic.py", line 42, in Textatistic
def __init__(self, text, abbr=Abbreviations(), hyphen=Hyphenator('en_US'), easy=EasyWords()):
File "D:\anaconda3\lib\site-packages\hyphen\hyphenator.py", line 64, in __init__
raise RuntimeError(f'C extension raised error \
RuntimeError: C extension raised error when initializing Hyphenator for dictionary at C:\Users\root\AppData\Local\pyhyphen\hyph_en_US.dic
Please tell me how to do!

Inherit parent class attributes, __init__, etc

I am trying to use a parent class as a blueprint for new classes.
E.g. the FileValidator contains all generic attributesand methods for a generic file. Then I want to create for example a ImageValidator inheriting everything from the FileValidator but with additional, more specific attribtues, methods. etc. In this example the child class is called: FileValidatorPlus
My understanding was, that if I inherit the parent class I can just plug-in more attributes/methods without repeating anything, like just adding min_size. But the following code gives: TypeError: FileValidatorPlus.__init__() got an unexpected keyword argument 'max_size'
class File:
def __init__(self, file_size=100):
self.file_size = file_size
class FileValidator(object):
error_messages = {'max_size': 'some error msg'}
def __init__(self, max_size=None):
self.max_size = max_size
def __call__(self, file):
print(self.max_size > file.file_size)
class FileValidatorPlus(FileValidator):
error_messages = {'min_size': 'some other error msg'}
def __init__(self, min_size=None):
super(FileValidatorPlus, self).__init__()
self.error_messages.update(super(FileValidatorPlus, self).error_messages)
self.min_size = min_size
validator = FileValidatorPlus(max_size=10, min_size=20)
print(validator.error_messages)
print(validator.max_size)
print(validator.min_size)
Full Traceback:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: FileValidatorPlus.__init__() got an unexpected keyword argument 'max_size'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_code_executor.py", line 108, in add_exec
more, exception_occurred = self.do_add_exec(code_fragment)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 90, in do_add_exec
command.run()
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_console_types.py", line 35, in run
self.more = self.interpreter.runsource(text, '<input>', symbol)
File "/usr/local/lib/python3.10/code.py", line 74, in runsource
self.runcode(code)
File "/usr/local/lib/python3.10/code.py", line 94, in runcode
self.showtraceback()
File "/usr/local/lib/python3.10/code.py", line 148, in showtraceback
sys.excepthook(ei[0], ei[1], last_tb)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 112, in info
traceback.print_exception(type, value, tb)
NameError: name 'traceback' is not defined
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 284, in process_exec_queue
interpreter.add_exec(code_fragment)
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_code_executor.py", line 132, in add_exec
return more, exception_occurred
UnboundLocalError: local variable 'exception_occurred' referenced before assignment
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 511, in <module>
pydevconsole.start_server(port)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 407, in start_server
process_exec_queue(interpreter)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 292, in process_exec_queue
traceback.print_exception(type, value, tb, file=sys.__stderr__)
UnboundLocalError: local variable 'traceback' referenced before assignment
Process finished with exit code 1
You need to add max_size as a parameter in your FileValidatorPlus constructor.
If you want FileValidatorPlus to inherit this field from the super's constructor, you must not define a __init__ method.
In other words, if you want FileValidatorPlus to inherit max_size parameter from FileValidator, you should delete __init__ because the subclass only inherits constructor properties when they don't have their own constructor.
But in your case I think that it would be a better solution just to add min_size=None to FileValidatorPlus.__init__:
def __init__(self, max_size=None, min_size=None):
super(FileValidatorPlus, self).__init__(max_size)
I got also different error :
TypeError: __init__() got an unexpected keyword argument 'max_size'
and the solution would be :
def __init__(self, max_size=None, min_size=None):
super(FileValidatorPlus, self).__init__(max_size)
Output:
{'min_size': 'some other error msg', 'max_size': 'some error msg'}
10
20

Shorten stack trace of exceptions?

I have a custom exception get raised when someone screws up with my library, which currently looks like this:
Traceback (most recent call last):
File "main.py", line 17, in <module>
StateMachine()
File "main.py", line 15, in __new__
activate(self)
File "/home/runner/va4un94x2qp/fsm.py", line 101, in activate
state = enable(machine, state)
File "/home/runner/va4un94x2qp/fsm.py", line 94, in enable
raise MissingReturnError("State '{}' in machine '{}' missing a return statement, or it returns None..".format(StateFound.fallmsg, machine.__name__))
fsm.MissingReturnError: State '__main__' in machine 'StateMachine' missing a return statement, or it returns None.
But I want it to look like this:
Traceback (most recent call last):
File "main.py", line 17, in <module>
StateMachine()
File "main.py", line 15, in __new__
activate(self)
MissingReturnError: State '__main__' in machine 'StateMachine' missing a return statement, or it returns None.
How do I do that, without any excepthook nonsense? (Because THAT doesn't just affect one exception, it affects all exceptions) I want to modify an exception. By the way, I've tried setting suppress_context to True, I've tried raising the exception from None. How else do I do it?
And if you ask, everything I want gone, isn't needed. All that is needed is the exception message, and the call of the activate() method.
And I'm not going to be messing with the Python interpreter, I'm going to be releasing this library to the public, and I want exceptions to look this way to everyone. (It's Python 3.X)

NameError python api "vishnubob/kinet"

So I am trying to run and learn all about the vishnubob/kinet api.
After I download it I try to run the example script (also after fixing a couple syntax errors) I get this error:
Traceback (most recent call last):
File "example.py", line 31, in <module>
pds = PowerSupply("192.168.1.121")
NameError: name 'PowerSupply' is not defined
I have no clue why this is happening, as the imports look good (to me at least).
If someone knows why or can point me to the right direction then I would be grateful.
The clue here is "fixing syntax errors". That code has been written for Python 2, and it uses a thing called implicit relative import which was removed in Python 3. Namely the line in kinet/__init__.py
from kinet import *
is trying to import from the top-level package in Python 3, when Python 2 defaulted to importing from a local module first (kinet/kinet.py). The fix is to change this to
from .kinet import *
However this leads down the rabbit hole, as kinet.py has more syntax errors, after which it just fails spectacularly with
Traceback (most recent call last):
File "example.py", line 31, in <module>
pds = PowerSupply("192.168.1.121")
File "./kinet/kinet.py", line 227, in __init__
self.header = Header()
File "./kinet/kinet.py", line 22, in __init__
self._struct = struct.Struct(self.struct_format)
File "./kinet/kinet.py", line 61, in __setattr__
if key not in self.Keys:
File "./kinet/kinet.py", line 56, in __getattr__
if key not in self.Keys:
File "./kinet/kinet.py", line 56, in __getattr__
if key not in self.Keys:
File "./kinet/kinet.py", line 56, in __getattr__
if key not in self.Keys:
[Previous line repeated 325 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
It is a bad piece of code written using all the syntax that was deprecated already in Python 2.6. I'd look for a Python 3 rewrite instead of trying to fix that.

Python: eliminating stack traces into library code?

When I get a runtime exception from the standard library, it's almost always a problem in my code and not in the library code. Is there a way to truncate the exception stack trace so that it doesn't show the guts of the library package?
For example, I would like to get this:
Traceback (most recent call last):
File "./lmd3-mkhead.py", line 71, in <module>
main()
File "./lmd3-mkhead.py", line 66, in main
create()
File "./lmd3-mkhead.py", line 41, in create
headver1[depotFile]=rev
TypeError: Data values must be of type string or None.
and not this:
Traceback (most recent call last):
File "./lmd3-mkhead.py", line 71, in <module>
main()
File "./lmd3-mkhead.py", line 66, in main
create()
File "./lmd3-mkhead.py", line 41, in create
headver1[depotFile]=rev
File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 276, in __setitem__
_DeadlockWrap(wrapF) # self.db[key] = value
File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/dbutils.py", line 68, in DeadlockWrap
return function(*_args, **_kwargs)
File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 275, in wrapF
self.db[key] = value
TypeError: Data values must be of type string or None.
update: added an answer with the code, thanks to the pointer from Alex.
The traceback module in Python's standard library lets you emit error tracebacks in a way that accords to your liking, while an exception is propagating. You can use this power either in the except leg of a try/except statement, or in a function you've installed as sys.excepthook, which gets called if and when an exception propagates all the way; quoting the docs:
In an interactive session this happens
just before control is returned to the
prompt; in a Python program this
happens just before the program exits.
The handling of such top-level
exceptions can be customized by
assigning another three-argument
function to sys.excepthook.
Here's a simple, artificial example:
>>> import sys
>>> import traceback
>>> def f(n):
... if n<=0: raise ZeroDivisionError
... f(n-1)
...
>>> def excepthook(type, value, tb):
... traceback.print_exception(type, value, tb, 3)
...
>>> sys.excepthook = excepthook
>>> f(8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in f
File "<stdin>", line 3, in f
ZeroDivisionError
as you see, without needing a try/except, you can easily limit the traceback to (for example) the first three levels -- even though we know by design that there were 9 nested levels when the exception was raised.
You want something more sophisticated than a simple limit on levels, so you'll need to call traceback.format_exception, which gives you a list of lines rather than printing it, then "prune" from that list the lines that are about modules you never want to see in your tracebacks, and finally emit the remaining lines (typically to sys.stderr, but, whatever!-).
Thanks to the pointer from Alex, here's teh codez:
def trimmedexceptions(type, value, tb, pylibdir=None, lev=None):
"""trim system packages from the exception printout"""
if pylibdir is None:
import traceback, distutils.sysconfig
pylibdir = distutils.sysconfig.get_python_lib(1,1)
nlev = trimmedexceptions(type, value, tb, pylibdir, 0)
traceback.print_exception(type, value, tb, nlev)
else:
fn = tb.tb_frame.f_code.co_filename
if tb.tb_next is None or fn.startswith(pylibdir):
return lev
else:
return trimmedexceptions(type, value, tb.tb_next, pylibdir, lev+1)
import sys
sys.excepthook=trimmedexceptions
# --- test code ---
def f1(): f2()
def f2(): f3()
def f3():
import xmlrpclib
proxy = xmlrpclib.ServerProxy('http://nosuchserver')
proxy.f()
f1()
Which yields this stack trace:
Traceback (most recent call last):
File "./tsttraceback.py", line 47, in <module>
f1()
File "./tsttraceback.py", line 40, in f1
def f1(): f2()
File "./tsttraceback.py", line 41, in f2
def f2(): f3()
File "./tsttraceback.py", line 45, in f3
proxy.f()
gaierror: [Errno -2] Name or service not known
The Traceback library is probably what you want. Here's one example that might help:
import traceback
try:
your_main()
except:
lines = traceback.format_exc()
print lines[:lines.find('File "/usr')]
(This obviously won't work if there's an exception outside the library, and might not exactly fit your needs, but it's one way of using the traceback library)
Put an unqualified try...except at the top of your code (ie: in your "main") or set sys.excepthook. You can then format the stack trace however you'd like.

Categories