Python Type is not defined - python-3.x

I want to do the semantic checking for a language and i use ANTLR4 to generate parser and visitor class. However i met a problem.
If i use this method print(type(newList[0].expression()))
I will get a type like this <class 'IDILParser.IDILParser.IdenetExpressionContext'>
However, if i run the code below, i will get a error like this NameError: name 'IDILParser' is not defined
Can i ask how to fix this problem? Thanks!
from antlr4 import *
if __name__ is not None and "." in __name__:
from .IDILParser import IDILParser
else:
from IDILParser import IDILParser
class IDILVisitor(ParseTreeVisitor):
def visitAssign(self, ctx:IDILParser.AssignContext):
if type(newList[0].expression()) is IDILParser.IDILParser.IdenetExpressionContext:
...

You did from IDILParser import IDILParser, which means the IDILParser in your code already acutally refers to IDILParser.IDILParser.
So try taking away that one layer:
if type(newList[0].expression()) is IDILParser.IdenetExpressionContext:
...
Btw, when in doubt if your code is being run as a module or as a script (aka relative imports do work or not), you could also do the following:
try:
from .IDILParser import IDILParser
except ImportError:
from IDILParser import IDILParser

Related

python 3, can't understand import system

this is such a simple problem but I cant seem to find any direct explanation to this.
in module.py
def foo():
print("foo")
in main.py
import module
foo()
it will result in an error saying that foo is not defined? when i look for the answer online, I can't find anything surprisingly
I'm not planning to use things like
from x import y
just straight up the import system
When you import an external module, it generates a variable named module that contains all classes, functions and variables from the module. To acess 'foo' function you need to first acess the module:
module.foo()
To import 'foo' function you can import everything from the module, like this:
from module import *
Now you can simply do: foo()
You can also set a custom name to the module, like:
import module as M
And now you can run 'foo' like this:
M.foo()
PS: I'm not english native
The statement
import module
makes the name of module module available. So you can use module.foo().
If you want to call foo() without "qualifying" it:
from module import foo
or
from module import *
but that latter is bad idea because you are liable to import unexpected names, which may collide with other names you imported from other modules.
from model import foo
is the preferred way as in any kinds of
from model import *
you (and anyone ever working on that code) has no idea what has been imported. Could even lead to name conflicts.

Python: cannot find reference to class when using import

I am new to python. I am using the anaconda prompt to run my code. I am trying to import a class from another module but I keep getting errors such as cannot find reference to the class.
P.S please don't negative mark this, or else I will lose the privilege of asking questions
I have already provided an __init__ function.
The module itself runs just fine.
I have used from parser import Parser
I have used from parser import * statement as well
My Parser class
class Parser(object):
def __init__(self, tokens):
self.tokens = tokens
self.token_index = 0
My main class
from parser import Parser
I expected it to normally import the class, but it is unable to.
I keep getting the cannot import name 'Parser' from 'parser' (unknown location) when I use from parser import Parser
parser is also the name of a Python module in the standard library.
It's likely there is a name conflict, and that Python is importing the module from the standard library.
I changed the module name to mparser and it works!

Catching Import errors and Name errors in Python during "compile" time

Can you catch import / name and other errors in python using a (linting) tool or a compilation step?
The other option is to make sure all possible code paths are tested (This is not always feasible, especially for large existing code bases and other reasons)
Here are some examples.
Missing import - caught by pylint, although as a syntax error instead of an import error.
def test():
print("Time now is ..", datetime.datetime())
pylint output:
E0602: Undefined variable 'datetime' (undefined-variable)
Import present, but incorrect method used. This passes both pylint and py_compile.
from datetime import datetime
def test():
print("Time now is ..", datetime.today2())
Edit: To add one more option.
Doing an import * shows some errors, but not errors in statements which are inside the functions.
This error is reported
from datetime import datetime
print("today2", datetime.today2())
Error :
Python 3.7.0 (default, Aug 22 2018, 15:22:56)
>>> from test import *
...
print("today2", datetime.today2())
AttributeError: type object 'datetime.datetime' has no attribute 'today2'
>>>
This is not.
from datetime import datetime
def test():
print("Time now is ..", datetime.today2())
In my experience, flake8 does a great job of catching missing imports and name errors. In order to catch missing imports, you must not use wildcard imports like "from foo import *", since it cannot guess which names that will create. Also, it cannot do these detections while syntax errors exist, so you have to fix those first.
Unlike c++ which is a compiled language, python is an interpreted language. Which means it doesn't have compile phase. It interpreted code line by line.
According to that, you didn't find the errors until you reach them in runtime.
If you want that errors appears, you should somehow path throw every line of your code. The best approach is using test libraries with 100% test coverage.
For more information look at this question and it's answers.

import module with name same as built-in module in python 3

I meet a similar problem which can be simplified as following:
For example I have a file structure as following:
----folder
---- main.py
---- math.py
I define a function in math.py and I want to import this math.py in main.py .
The codes in math.py is following
# math.py
def f(x) :
return x**3
If I write codes in main.py as following
# main.py
import math
def main() :
print(math.f(3))
if __name__ == "__main__":
main()
then it returns AttributeError: module 'math' has no attribute 'f'
If I write codes in main.py as following
# main.py
from . import math
def main() :
print(math.f(3))
if __name__ == "__main__":
main()
Then it returns ImportError: cannot import name 'math' from '__main__' (main.py)
My question:
If I only want to import the module math.py in path folder which has the same name as build-in module, what should I do?
If in the main.py I want to use both math.f(x) defined in my math.py and built-in math.acos(x), what should I do?
PS: I meet similar problem since I have a long codes written by someone ten years ago. At that time there is no built-in module with such name (In fact it's not math module. I just simplify the problem by above question). And the functions of this module have been used at many places. Therefore it's almost impossible to change module's name since if so I need to carefully change all sites module.function().
It's pretty bad practice to name your modules after built-in modules. I'd recommend naming your math.py something else.
That being said, you could import it using the path with imp:
import imp
math = imp.load_source('math', './math.py')
Dove into a bit of a rabbit hole but here we go. As a disclaimer, like Jack said naming modules after builtins is very bad practice, and this can more easily be accomplished using imp as he suggested.
The reason you're having problems come from the interaction of a few things. When you type
import math
What your python does is look at sys.path. It will check in all the locations in sys.path for a module named math, and import the first one it finds. In your case, it finds your local math module first. After the import is completed, it adds it to sys.modules, but we'll get back to that.
Since you want to use both, first you can import your local math as you have. I would suggest importing it as a different name to keep it separate.
from . import math as local_math
After that, we need to mess with our sys.path to find the builtin math
sys.path = sys.path[::-1]
This reverses the order of sys.path, meaning it will look in your local directory first instead of last.
Now you might think this was enough, but if you try to import math here, python will see it in sys.modules and not bother trying to import again, so first
del sys.modules['math']
Then we can import the default math module
import math
and finally clean up our sys.path
sys.path = sys.path[::-1]
now we have access to everything we need
>>>math.cos(10)
-0.8390715290764524
>>>local_math.f(10)
1000
According to official docs: https://docs.python.org/3/library/imp.html
imp will be removed in version 3.12
Deprecated since version 3.4, will be removed in version 3.12: The imp module is deprecated in favor of importlib.
From imp approach (Deprecated):
import imp
m = imp.load_source('math', './math.py')
m.foo()
To importlib approach with the minimum code 'impact' would be:
def load_module(name, path):
from importlib import util as importlib_util
module_spec = importlib_util.spec_from_file_location(name, path)
module = importlib_util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
return module
m = load_module('math', './math.py')
m.foo()

Import an Error class from a package in python

How can I import the Error class (and only the error class, not a namespace) in python to be used in an exception handling?
What's not intended to be used:
from tkinter import _tkinter as tk
try:
...
except tk.TclError:
print('Oops. Bad window path.')
I've tried the above, which works but doing so also imports a bunch of other things into my namespace that I don't need and I also need to use tk.TclError to reference it instead of simply TclError.
What I try to avoid, since it imports the whole package that I do not need, I solely need to handle the exception:
import tkinter as tk
try:
...
except tk.TclError:
print('Oops. Bad window path.')
So how do I import the Error class alone from the package, without getting the whole tkinter namespace, if that's even possible or recommandable?
I have two seperate Programs, I'll call them A and B here to shorten it.
What I would like to achieve
A.py
## Communicator ##
import B
#... Some irrelevant code ...
GUI = B.start()
try:
#Tell the GUI to modify something, for example:
GUI.entry.insert(0, 'Input')
except TclError:
#Modification failed due to Bad Window Path
B.py
## GUI ##
import tkinter as tk
#Little Function to give the Communicator the required object to start/handle the GUI
def start():
root = tk.Tk()
run = Alarmviewer(root)
return run
#... GUI initialization, creating/destroying of windows, modifications, etc
The TclError class can be imported from tkinter. To make it available as tk.TclError just import tkinter with the name tk:
import tkinter as tk
try:
...
except tk.TclError:
...
You can, of course, import just the TclError exception if you wish, though it really doesn't have any actual advantage over importing the entire module in this particular example:
from tkinter import TclError
try:
...
except TclError:
...
Your question claims you must reference it as tk.TclError, but that is a false statement. You reference it by the name you import it as. The name is irrelevant, what is important is the actual exception object itself.
For example, create a file named gui.py, and in that file put this:
# gui.py
import tkinter as tk
def do_something():
raise tk.TclError("something bad happened")
Next, in another file add the following code:
from tkinter import TclError
import gui
try:
gui.do_something()
except TclError:
print("I caught the TclError")
When you run the code, you should see "I caught the TclError" printed.

Resources