How can I uncache imported module in python? - python

This is really freaking me out. My project looks like this
.
|-- main.py
|-- classes
| |-- __init__.py
| |-- exceptions.py
In those exceptions.py, I initally created one exception called SecurityError:
class SecurityError(Exception):
pass
I included the file in main.py using from classes.exceptions import * and SecurityError normally works when I just raise it.
Afterwards, I also added FilesystemError, but whenever using it, I get:
global name 'FilesystemError' is not defined
I tried to delete *.pyc files in classes directory but it has no effect. Any changes to the exceptions.py take no effect, including any ridiculous ones that make the file invalid:
class FileFOO BAR BAZ systemError(Exception):
pass
class SecurityErr foo bar bazor(Exception):
pass
The program still behaves as if the file never changed since the first run. I don't think this behaviour has anything to do with intuitive programming - if there's cache, it should be in that directory.
I am running the python directly from command line:
C:\programing\python\MyProject>py -2 main.py

Confusing errors of the form global name 'XXX' is not defined typically mean that you are shadowing a standard library module. You must rename your exceptions module.

Related

Python Comprehension - Importing & Dunder Methods

Python Double-Underscore methods are hiding everywhere and behind everything in Python! I am curious about how this is specifically working with the interpreter.
import some_module as sm
From my current understanding:
Import searches for requested module
It binds result to the local assignment (if given)
It utilizes the __init__.py . . . ???
There seems to be something going on that is larger than my scope of understanding. I understand we use __init__() for class initialization. It is functioning as a constructor for our class.
I do not understand how calling import is then utilizing the __init__.py.
What exactly is happening when we run import?
How is __init__.py different from other dunder methods?
Can we manipulate this dunder method (if we really wanted to?)
import some_module is going to look for one of two things. It's either going to look for a some_module.py in the search path or a some_module/__init__.py. Only one of those should exist. The only thing __init__.py means when it comes to modules is "this is the module that represents this folder". So consider this folder structure.
foo/
__init__.py
module1.py
bar.py
Then the three modules available are foo (which corresponds to foo/__init__.py), foo.module1 (which corresponds to foo/module1.py), and bar (which corresponds to bar.py). By convention, foo/__init__.py will usually import important names from module1.py and reexport some of them for convenience, but this is by no means a requirement.

Is it right to import variables from __init__ into a unit-test script?

Let's say that we have a directory with the following structure:
tests/
|-- __init__.py
|-- test_foo.py
where package foo is tested. In test_foo.py, variable bar is defined (and modified) to later be used.
Now imagine that instead of one file, we have around 20 test_fooX.py, where bar is initialized in every test.
Is it good practice to initiate bar in __init__.py and import it directly in every test? E.g.
from __init__ import bar
The Zen of python mentions that:
Explicit is better than implicit.
Defining bar in every single script would be what the explicit way. However, importing variables improves the structure of the tests/project.
A real scenario would be a logger (imported from foo), whose logging level needs to be changed; or the location of a specific directory instead of defining it every time.
There's nothing really implicit about __init__.py. A package is a module. Because a package is implemented by a directory containing a file named __init__.py, that file contains the contents of the module tests, with other files implementing submodules belonging to the same package.

How does pytest_plugin Global variable works?

I was trying to define bunch fixtures in one file say redis.py (abc\plgfix\redis.py) and use them in my test cases (abc\common\test_file.py) via pytest_plugin. While doing that I notice test cases couldn't see fixtures I defined.
My Folder structure is as follows
abc
|
common
|
config.py ( I have defined pytest_plugin=["plgfix.redis"]
test_file.py
plgfix
|
redis.py ( I have defined bunch of fixtures here)
__init__.py
From above illustration
-> plgfix (folder) has my desired file(redis.py) and __init__.py file to
make folder as package.
-> In abc\common\config.py. I have defined pytest_plugin global variable
pytest_plugins = ["plgfix.redis"] #assuming all fixtures in
#redis.py file , available for test cases
-> Now I have created abc\common\test_file.py where I'm using one of the
defined fixture in redis.py (abc\plgfix\redis.py) as follows.
def test_fixtu(fix1):
print ("Hi")
pass
I was getting error as fix1 is not found
Note : I can able to import config file and see contents as 'package', 'spec', 'pytest_plugins'....... (confirming it is not path issue)
According to the pytest docs, the global var is supposed to be either a str or a Sequence[str]. You seem to have assigned a list to it.

What is the scope of imports defined in the package __init__.py file?

For a project I had to switch from C++ to python but I'm having some trouble fully understanding the __init__.py file. I found the following documentation on the __init__.py file:
https://docs.python.org/3/tutorial/modules.html
https://www.pythoncentral.io/how-to-create-a-python-package/
http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html
To get more familiar with the way the __init__.py file works I did some tests in both python 2.7 and 3.6.5. I used the "PythonCentral" test pacakge (see link 2) for this:
Now I understand the following about the __init__.py file:
The __init__.py file executes when a module or subpackage module is imported.
The __init__.py can be used to overload the package __all__ method.
The __init__.py can be used to define the import order
The __init__.py can be used to make classes available on package and subpackage level.
Using the different modules and classes from the scope of my main file seems to go as explained in the documentation. However when trying to use a class that is defined in another subpackage module I run into troubles. In python 2.7 created the following __init__.py file in the subanimals subpackage:
from Mammals import Mammals
print "subpackage __init__.py executed"
Following I created the following code inside the Bird.py module:
class Birds:
def __init__(self):
''' Constructor for this class. '''
# Create some member animals
self.members = ['Sparrow', 'Robin', 'Duck']
def printMembers(self):
print('Printing members of the Birds class')
for member in self.members:
print('\t%s ' % member)
test = Mammals()
test.printMembers
When running the main following main script:
from animals.subanimals import Birds
test = Birds()
test.printMembers()
I keep getting the global name Mammals not defined. I can solve this in python 2.7 by adding from Mammals import Mammals to the top of the Birds.py.
Does the __init__.py only import packages and classes on the scope level of the main script and therefore not inside the Birds.py module or am I doing something else wrong?
Answer to my question can be found in #jonrsharpe 's comment.
Each individual file must be valid on its own, defining all
appropriate imports. init.py is for aggregating multiple files in
a directory into a single module; think of it as grouping and passing
attributes up to the parent, not down to the other files in that
directory.

Interpreter thinks 2 declarations of the same class are different

Basically I have a project set up like so:
<container-folder>
|- <folder_1>
|- <extra_folder>
| |- source.py
|
|- main.py
And in main.py I declare a class like so:
class ClassOne:
pass
and in another method in main.py I have the following code:
result = source_function()
if not isinstance(result, ClassOne):
print "failed!"
In source.py, I define
import container-folder.folder_1.main
...
def source_function():
return main.ClassOne()
However, I still get "failed!" printed out. When examining in the debugger, I got a bit of an odd surprise:
result was marked as type container-folder.folder_1.main.ClassOne, and ClassOne has the signature main.ClassOne. Why are these two not considered equal?
I also noted that if I changed the code to the following, using its fully-qualified class name:
if not isinstance(result, container-folder.folder_1.main.ClassOne):
I get the expected success.
They are not the same class. This is due to a quirk in that when you run a python module (ie. python main.py) it gets run as __main__. Thus you have __main__.SomeClass (from the root module of the program) and main.SomeClass (from the module imported by source) , which are different classes from different modules.
To solve your problem it is best to move the class to another module and have both main and your source import SomeClass from this third module.
Technically you could also import SomeClass from __main__, but then you get into all sorts of tricky problems with circular dependencies.

Categories