I' working on a Python project with a directory structure similar to this:
foo/
├── bar
│ ├── bar1.py
│ ├── bar2.py
│ └── __init__.py
└── __init__.py
Where the module bar1 defines the function function1.
I would like to have users of my code import function1 (and nothing else) directly from foo, i.e. via from foo import function1. Fair enough, that can be achieved with the following foo/__init__.py:
from .bar.bar1 import function1
__all__ = ['function1']
The problem now is that someone running import foo in e.g. the REPL will still be presented with foo.bar alongside foo.function1 when trying to autocomplete foo.. Is there a way to "hide" the existence of bar from users without changing its name to _bar?
I might be going about this the wrong way alltogether so I'm open to suggestions on how to restructure my code but I would like to avoid renaming modules.
You can hide it with deleting bar reference in foo/__init__.py:
from .bar.bar1 import function1
__all__ = ['function1']
del bar
Existence of __all__ affects the from <module> import * behavior only
Related
I am trying to make a package that has 2 subpackages. The directory structure looks like this:
project_folder
└── package_name
├── __init__.py
├── subpackage1
├── __init__.py
├── script1.py
├── subpackage2
├── __init__.py
├── script2.py
The __init__.py file in package_name is empty. The __init__.py in subpackage1 looks like this:
from .subpackage1 import *
and let's say script1.py has this function:
def add(a, b):
return a+b
Now script2.py in subpackage2 has a collection of functions that may use some of the functions of script1.py. Let's say script2.py looks like this:
def add_extended(a, b):
return add(a,b) + a
I have read many posts on StackOverflow, but so far I have not managed how to import a submodule that has dependencies on other submodules. I have tried to make __init__.py in subpackage2 look like this:
from .subpackage2 import *
from ..subpackage1.script1 import add
In my mind, I am setting subpackage2 in a way that when it is imported, the function add from subpackage1 is also imported because .. is looking for subpackage1 in the parent directory. However, when I run a script like this:
from package_name.subpackage2 import add_1
a, b = 2, 4
add_extended(a,b)
It raises a NameError: name 'add' is not defined, so it pretty much is telling me that the function add from submodule subpackage1 is not being imported properly when importing subpackage2.
I am using Python 3.8 on Windows 10.
EDIT
Interestingly, if I import the functions from subpackage1 on script2.py itself instead of on __init__.py:
from ..subpackage1.script1 import add
def add_extended(a, b):
return add(a,b) + a
the script below works:
from package_name.subpackage2 import add_1
a, b = 2, 4
add_extended(a,b)
However, I believe that is not how the package is supposed to work. Am I missing any file that should be added to enable me do what I want to do?
I am struggling with nested __init__.py in a Python package I am writting. The Package has the following architecture:
module/
├── __init__.py
├── submodule1
│ ├── __init__.py
│ └── source.py
└── submodule2
├── __init__.py
├── source.py
└── subsubmodule2
├── __init__.py
└── source.py
My intent is to be able to access functions defined in submodule2/source.py through module.submodule2.function and in subsubmodules2/source.py through module.submodule2.subsubmodule2.function.
The first thing I tried was to define __init__.py in submodule2 this way:
from .subsubmodule2 import *
But doing so, I get the functions defined in subsubmodules2/source.py through module.submodule2.function (and module.function).
If I do:
from . import subsubmodule2
I get these functions through module.subsubmodule2.function.
I also tried to define __all__ keyword in __init__, with no more success. If I understand well Python documentation, I guess I could leave empty __init__.py files and it could work, but from my understanding that is not the best practice either.
What would be the best way to access these functions as intended in my module?
in module __init__.py file write the module which you want to import as
from . import submodule1
from . import submodule2
__all__ = ['submodule1', 'submodule2']
Now, in submodule1 __init__.py file write
from . import source
from . import subsubmodule
# if you want to import functions from source then import them or in source.py
# define __all__ and add function which you want to expose
__all__ = ['source', 'subsubmodule']
now in subsubmodule __init__ file define function or class which you want to expose
from . source import *
__all__ = ['source']
# if you want to use * as import, i suggest you to use __all__ in source.py and mention all exposed function there
The __init__.py file represents its respective package. For example, module/submodule2/__init__.py represents module. submodule2 .
In order to pull objects defined in submodules into their package namespace, import them:
# module/submodule2/__init__.py
from .source import *
Since __init__.py is a regular Python module, one can also forgo a separate .source module and define objects directly inside __init__.py:
# module/submodule2/__init__.py
def function():
...
Note that subpackages themselves are already available as their respective name. One does not have to – and in fact should not – import them in the parent module. They will be imported if code using the package imports them.
I have a beeware project and also want to use my own modules in it like Models and Controllers. Also, a module which creates some objects I can test with.
But when I want to import the module to create the test objects and use the method it just throws an error:
ImportError: attempted relative import beyond top-level package
After some research, I know that the path (directory) structures, where I put my modules in, and where the package is, are important. But where ever I put the modules it has the same (or kinda like this) errors. But I can import my Models to create objects of these classes. I also can't decide where the start point of the briefcase is.
Here my structure currently:
/Project_Dir (own created)
/briefcase_project (created from briefcase)
/src
/Models (own created)
/app_directory (created from briefcase)
here is the __main__.py and the __init__.py (the start point I guess) and the app.py (where beeware code is, and also my module import from Test)
/Test (own created, here is a file with a method I want to call)
Sadly there is not so much stuff to find about beeware so I could find a solution.
Please help. Thanks ^^
I did the following to workaround the issue. The example using the Beeware Tutorial 2 source code is on Github
.
├── __init__.py
├── __main__.py
├── app.py
├── mylib <--- # my lib.
│ ├── __init__.py
│ └── testlib.py
└── resources
├── __init__.py
├── beewarecustomlibexample.icns
├── beewarecustomlibexample.ico
└── beewarecustomlibexample.png
2 directories, 9 files
The mylib/testlib.py
def test(text: str) -> str:
return f"Hello: {text}"
In the app.py:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
from beewarecustomlibexample.mylib.testlib import test # Import custom lib
class BeewareCustomLibExample(toga.App):
def startup(self):
...
def say_hello(self, widget):
# Calling my test method
result = test(self.name_input.value)
self.main_window.info_dialog("Test Dialog", result)
def main():
return BeewareCustomLibExample()
The above is how I got it working. I've built it on MacOS and works fine.
Take your project folder name and then import from there, so if you're tinkering with the tutorial and you've set up a module folder called myModule in the same directory as your app.py and you have a file called file.py with a class called myClass, you might type:
from helloworld.myModule.file import myClass
I was having trouble with circular dependencies, only to find some advice online that I'm better off importing an entire module rather than specific items within a module. Prior to the circular dependency issue, I was having no issue with imports.
So with the blog's advice, I setup a __init__.py in a folder containing a few models, imported each there, and now when I try to import from that module, I'm being told that module doesn't have an attribute I'm looking for.
So I have this file structure:
└── root
├── models
│ ├── __init__.py
│ ├── a.py
│ └── b.py
└── c.py
In __init__.py, I have
from models.a import A
from models.b import B
And in c.py
import models
# code
models.A.func()
But I get the error module 'models' has no attribute 'A'. As A and B both reference each other, I was getting circular imports at first, but now that they're resolved, I can't get the models to show up at all.
You either need to add your project's directory to PYTHONPATH or you need to do
from . import models
your __init__.py file doesn't require any change. I think in c.py file, type as follows :
modele_name.function_name()
If u have imported that function in your __init__.py file, this will help you, I suppose.
For more details, please edit your question and add the git link of your repo
I would like to know why I need to include the main directory name in the import statements for creating my project's directory structure.
My project's structure
.
├── main.py
├── myModel
│ ├── __init__.py
│ ├── loader
│ │ ├── __init__.py
│ │ └── dataset_loader.py
│ └── models
│ ├── __init__.py
│ ├── static_model.py
│ └── task_model.py
└── tree.txt
main.py
from myModel import loader
from myModel import models
loader.fun ()
loader.dataset_loader.fun ()
myModel/__init__.py
import myModel.models
import myModel.loader
myModel/loader/__init__.py
from myModel.loader.dataset_loader import *
myModel/models/__init__.py
from myModel.models.static_model import StaticModel
My first question is why I need to put myModel even in subfolders of the myModel directory. I tried to remove it, but import didn't work so I think it needs to be there.
Secondly, why I can call fun directly from loader and not using the full qualified path?
I read something on the web. But I still have trouble understanding why this happens.
Absolute imports, like import x.y.z or from x.y import z require x to be in your path. In your specific case, myModel is on the path because of your working directory. The sub-packages are not on the path, and can therefore only be accessed by reiterating the root package.
A more intuitive approach might be to use relative paths. This is possible because all your files live in proper packages with __init__ files. Keep in mind that relative paths imply that you have modules that are designed to live in your package structure and not on their own. Otherwise, you may end up causing errors when you try to run some of the modules as standalone scripts.
Change myModel/__init__.py to:
from . import models
from . import loader
The . makes the import relative. Notice that I did not suggest changing main.py, since it lives outside your packages. Adding more dots lets you go up more levels in the file hierarchy.
Change myModel/loader/__init__.py to
from .dataset_loader import *
and myModel/models/__init__.py to
from .static_model import StaticModel
An import statement binds a name in your local namespace (usually the module you are executing it in). The name that is bound depends on which form of import you used:
import x binds the module described in x.py or x/__init__.py to the name x
import x.y binds the module described in x.py or x/__init__.py to the name x, and insures that x has an attribute y, either as an attribute defined in x.py/__init__.py, or as a sub-module in x/y.py.
from x import y binds the attribute or sub-module y from x.py/x/__init__.py or x/y.py to the name y. This option loads, but does not give you access to x.
When you run from myModel import loader, you get a module object loader that has a callable attribute fun.