Python Import NameError - python

I have a flask application structured like so:
/public_html
/content
/accounts
__init__.py
/classes
__init__.py
mycode.py
/forms
__init__.py
myform.py
/routes
__init__.py
myroute.py
/activity
/comments
/media
/messages
...
__init__.py
/media
__build__.py
__config__.py
The init in public_html/content looks something like this:
from accounts.classes.mycode import *
from accounts.forms.mycode import *
from accounts.routes.mycode import *
#..... etc .... until I've imported all the packages
and in each file, like mycode.py I have a circular import back to content like so:
from content import *
#The rest of my code goes here.
It has worked well for me but I've run into a bit of an issue structuring the rest of the imports as I need to call modules from say: accounts.routes.mycode
before it is actually imported. As a result I end up getting NameError: global name 'functionincode' is not defined.
I can fix the problem temporarily by importing the different functions at times there is no conflict but my code is becoming nasty. I really don't want to have this big mess of imports that all depend on one another in a specific order.
Is there any way I can go about re-structuring the imports so that there won't be a conflict? I was thinking in each package, like content.accounts having the init.py import everything there then in each accounts.classes.mycode.py importing everything else like:
from accounts import *
from activity import *
etc ...
However I am hopeful that there will be a bit of an easier fix.
Thanks!

Related

Python: Issue with modules in package importing each other

Path structure:
base.py
my_module/
__init__.py
mod1.py
mod2.py
base.py:
from my_module.mod2 import *
mod2_func2() # This call will work
my_module/mod1.py:
from mod2 import *
def mod1_func():
mod2_func1("Hello World") # This call will not work.
my_module/mod2.py:
from mod1 import *
def mod2_func1(input_text):
print(input_text)
def mod2_func2():
mod1_func() # This call will work
This code will error out because mod2_func1 is not defined. If I run mod1.py directly (i.e. adding code to an __name__=="__main__" block, it will work fine.
This is a reduced example of my real problem, which involves a bunch of modules inside a package all needing to talk to each other like this. The main thing is ensuring that mod1 and mod2 can access each others contents in the local namespace irrespective of which is called from base. I've looked at a ton of documentation on python namespace stuff, importing, and packages and while I'm relieved to find that it seems frustrating to everyone, I haven't found a solution. Any advice?

Import local packages in python

i've run through many posts about this, but still doesn't seem to work. The deal is pretty cut. I've the got the following hierarchy.
main.py
DirA/
__init__.py
hello.py
DirB/
__init__.py
foo.py
bla.py
lol.py
The__init__.py at DirA is empty. The respective one at DirB just contains the foo module.
__all__.py = ["foo"]
The main.py has the following code
import DirA
import DirB
hey() #Def written at hello.py
foolish1() #Def written at foo.py
foolish2() #Def written at foo.py
Long story short, I got NameError: name 'foo' is not defined. Any ideas? Thanks in advance.
You only get what you import. Therefore, in you main, you only get DirA and DirB. You would use them in one of those ways:
import DirA
DirA.something_in_init_py()
# Importing hello:
import DirA.hello
DirA.hello.something_in_hello_py()
# Using a named import:
from DirA.hello import something_in_hello_py
something_in_hello_py()
And in DirB, just make the __init__.py empty as well. The only use of __all__ is for when you want to import *, which you don't want because, as they say, explicit is better than implicit.
But in case you are curious, it would work this way:
from DirB import *
something_in_dirb()
By default the import * will import everything it can find that does not start with an underscore. Specifying a __all__ restricts what it imported to the names defined in __all__. See this question for more details.
Edit: about init.
The __init__.py is not really connected to the importing stuff. It is just a special file with the following properties:
Its existence means the directory is a python package, with several modules in it. If it does not exist, python will refuse to import anything from the directory.
It will always be loaded before loading anything else in the directory.
Its content will be available as the package itself.
Just try it put this in DirA/__init__.py:
foo = 42
Now, in your main:
from DirA import foo
print(foo) # 42
It can be useful, because you can import some of your submodules in the __init__.py to hide the inner structure of your package. Suppose you build an application with classes Author, Book and Review. To make it easier to read, you give each class its own file in a package. Now in your main, you have to import the full path:
from myapp.author import Author
from myapp.book import Book
from myapp.review import Review
Clearly not optimal. Now suppose you put those exact lines above in your __init__.py, you may simplify you main like this:
from myapp import Author, Book, Review
Python will load the __init__.py, which will in turn load all submodules and import the classes, making them available on the package. Now your main does not need to know where the classes are actually implemented.
Have you tried something like this:
One way
from DirA import hello
Another way
from DirA.hello import hey
If those don't work then append a new system path
You need to import the function itself:
How to call a function from another file in Python?
In your case:
from DirA import foolish1, foolish2

chained imports from subdirectory in python

I am using someone elses project to add some functionality to mine, and there is a python script I want to import. The problem comes with the import structure of their directories: I have placed their project directory in a subfolder under my main project (needs to stay there so I can keep their project out of my version control) it looks like this:
myproject/
myscript.py
theirproject/
__init__.py
baz.py
secondlayer/
__init__.py
all.py
foo.py
bar.py
all.py is simply a list of import statements which import additional scripts from the secondlayer directory like this:
from secondlayer.foo import *
from secondlayer.bar import * #etc
I would like to import:
from theirproject.secondlayer.all import *
but that fails when python complains "no module named secondlayer.foo"
I have also tried the following:
from theirproject.secondlayer import all
I can get it to work when I place my script in theirproject/ and import all without the "theirproject" prefix, but I really cant have it be like that. I can get further through the import process by importing foo, bar, etc individually like this:
from theirproject.secondlayer import foo
from theirproject.secondlayer import bar #etc
But then those scripts fail to import more stuff from still other scripts (like baz.py) at the same level as secondlayer, so im stuck.
Whats the right way to do this in python 2.7.6?
If you change
from secondlayer.foo import *
from secondlayer.bar import *
to user relative imports like this
from .foo import *
from .bar import *
or like this
from foo import *
from bar import *
it works.
Plus you could do these imports in the __init__.py at secondlayer level so that the import from myscript.py becomes
from theirproject.secondlayer.all import *
See if you have the necessary permissions to import the package from your directory and its corresponding sub directories.
For reference, you may like to see this and its corresponding linked questions :
Python Imports do not work
I ended up solving my problem by adding theirproject/ to my PYTHONPATH. I upvoted junnytony's answer - it helped point me in the right direction, so thanks!

Change main package name in python

In my project I want to change the main package name.
I've a dir structure like this:
hallo/sub
hallo/foo
hallo/bar
And I want to change the main name for example to 'goodbye':
goodbye/sub
goodbye/foo
goodbye/bar
But as result the new name is always rejected! for example if I import
import goodbye.sub.utils as utils
It return the error
ImportError: No module named sub.utils
And clearly the old name don't works.
The file __init__.py is written in all subdirectories!
I've tried to remove all *.pyc files and cache directory, I've tried to re-clone the project in another directory, but nothing, the new name is always rejected!
I'm using python2 under *nix and I'm never moved under windows.
Some idea?
Edit:
The old name works perfectly:
import hallo.sub.utils as utils
Has always worked without any errors, the problem is the name change.
For imports from the outside, check the contents of __init__.py for variables that can throw things off -- like __all__.
Also, the typical idiom is:
from hallo.sub import utils #tyically this
import hallo.sub.utils as utils #instead of this
I can't imagine why that would make a difference, but python occasionally has silly bugs.
For imports from within the package, you can instead use relative imports. Within your hallo package you can change this:
import hallo.sub as sub
import hallo.sub.utils as utils
to this
from . import sub
from .sub import utils
Then it doesn't matter what the outer package is called.

How to organize code with __init__.py?

I am just starting off using google app engine, and have been looking around for good practices and code organization. Most of my problems lie from confusion of __init__.py.
My current test structure looks like
/website
main.py
/pages
__init__.py #1
blog.py
hello2.py
hello.py
/sub
__init__.py #2
base.py
I am trying to use main.py as a file that simply points to everything in /pages and /pages/sub. Most modules in /pages share almost all the same imports (ex. import urllib), is there a way to define that everything in /pages imports what I want rather than adding it in every individual module?
Currently in __init__.py #1 I have
from sub.base import *
Yet my module blog.py says BaseHandler (a function in base.py) not defined.
My end goal is to have something like ...
main.py
from pages import *
#be able to call any function in /pages without having to do blog.func1() or hello.func2()
#rather just func1() and func2()
And to be able to share common imports for modules in /pages in __init__.py. So that they share for example urllib and all functions from base.py. Thank you for taking the time to read this post, I look forward to your insight.
Sounds like you think __init__.py is an initializer for the other modules in the package. It is not. It turns pages into a package (allowing its files and subdirectories to be modules), and it is executed, like a normal module would be, when your program calls import pages. Imagine that it's named pages.py instead.
So if you really want to dump everything into the same namespace, init #2 can contain from base import * (which will import everything in base to the namespace of sub), and blog.py can contain from sub import *. Got it?

Categories