Python - importing package classes into console global namespace - python

I'm having a spot of trouble getting my python classes to work within the python console. I want to automatically import all of my classes into the global namespace so I can use them without any prefix.module.names.
Here's what I've got so far...
projectname/
|-__init__.py
|
|-main_stuff/
|-__init__.py
|-main1.py
|-main2.py
|
|-other_stuff/
|-__init__.py
|-other1.py
|-other2.py
Each file defines a class of the same name, e.g. main1.py will define a class called Main1.
My PYTHONPATH is the absolute path to projectname/.
I've got a python startup file that contains this:
from projectname import *
But this doesn't let me use my classes at all. Upon starting a python console I would like to be able to write:
ob=Main1()
but Main1 isn't within the current namespace, so it doesn't work.
I tried adding things to the __init__.py files...
In projectname/__init__.py:
import main_stuff
In projectname/main_stuff/__init__.py:
import other_stuff
__all__ = ["main1", "main2", "main3"]
And so on. And in my startup file I added:
from projectname.main_stuff import *
from projectname.main_stuff/other_stuff import *
But to use the classes within the python console I still have to write:
ob=main1.Main1()
I'd prefer not to need the main1. part. Does anyone know how I can automatically put my classes in the global namespace when using the python console?
Thanks.
==== EDIT ====
What I need is to import a package at the class level, but from package import * gives me everything at the module level. I'm after an easy way of doing something like this:
for module in package do:
from package.module import *
==== ANOTHER EDIT ====
I ended up adding the class imports to my python startup file individually. It's not ideal because of the overhead of maintaining it, but it does what I want.
from class1.py import Class1
from class2.py import Class2
from class3.py import Class3

You want to use a different form of import.
In projectname/main_stuff/__init__.py:
from other_stuff import *
__all__ = ["main1", "main2", "main3"]
When you use a statement like this:
import foo
You are defining the name foo in the current module. Then you can use foo.something to get at the stuff in foo.
When you use this:
from foo import *
You are taking all of the names defined in foo and defining them in this module (like pouring a bucket of names from foo into your module).

Related

Cannot import module that imports a custom class [duplicate]

This question already has answers here:
Relative imports for the billionth time
(12 answers)
Closed 3 months ago.
I have a directory and module design that looks like this:
MyProject --- - script.py
|
- helpers --- - __init__.py
|
- class_container.py
|
- helper.py
# class_container.py
class MyClass:
pass
# helper.py
from class_container import MyClass
def func():
# some code using MyClass
# script.py
from helpers.helper import func
When I run script.py:
ModuleNotFoundError: No module named 'class_container'
I tried changing the code in helper.py such as:
# helper.py
from helpers.class_container import MyClass
def func():
# some code using MyClass
Then running script.py started working. But when I explicitly run helper.py:
ModuleNotFoundError: No module named 'helpers'
I want to be able run both script.py and helper.py separately without needing to change the code in any module.
Edit: I figured a solution which is changing helper.py such as:
from pathlib import Path
import sys
sys.path.append(str(Path(__file__).parent))
from class_container import MyClass
def func():
# some code using MyClass
Basically I added the directory of helper.py to sys.path by using sys and pathlib modules and __file__ object. And unlike import statement's behaviour, __file__ will not forget it's roots when imported/used from a different module (i.e it won't become the path of script.py when imported into it. It'll always be the path of helper.py since it was initiated there.).
Though I'd appreciate if someone can show another way that doesn't involve messing with sys.path, it feels like an illegal, 'unpythonic' tool.
You have to create a __init__.py file in the MyProject/helpers directory. Maybe you already have created it. If not, create an empty file.
Then in the MyProject/helpers/helper.py, access the module helpers.class_container like this.
from helpers.class_container import MyClass
def func():
# some code using MyClass
You can also use a relative import like this.
from .class_container import MyClass
If you want to run the MyProject/helpers/helper.py independently, add test code in helper.py like this.
from helpers.class_container import MyClass
def func():
# some code using MyClass
if __name__ == '__main__':
func()
And run like this in the MyProject directory.(I assume a Linux environment.)
$ python3 -m helpers.helper
The point is to differentiate Python modules from Python scripts and treat them differently.

ModuleNotFound Error with VSCode Python 3.8.2

I'm a greenhorn, so go easy on me:
I've been trying to divide up a python project I was working on into smaller parts. To that end I created 4 Classes inside a single folder in VSCode, one being a main class that imports the other 3 and accesses their methods etc.
The structure is as following:
top_level_folder
|--lower_level_folder
|--class1.py
|--class2.py
|--class3.py
|--mainclass.py
Now my mainclass is supposed to import the other 3 classes, via
from top_level_folder.lower_level_folder import class1
etc.
However, doing it this way, I get a ModuleNotFound Error (no module named top_level_folder)
import class1
etc
results in a TypeError
and
import top_level_folder.lower_level_folder.class1 as x
doesn't work either
Is there something obvious I'm missing? Is it down to my VSC installation?
It depends. If you're running mainclass.py as your executable script, your import should look like this
mainclass.py
from class1 import MyClass
But if you're planning on importing the module from outside the folder, you'll either need an __init__.py file, or you would specify the folder name. I.e your file structure looks like this
top_level_folder
|--lower_level_folder
|--__init__.py
|--class1.py
|--class2.py
|--class3.py
|--mainclass.py
|--main.py
your would import like this
main.py
from mainclass import MyClass
mainclass.py
from lower_level_folder.class1 import MyClass2
__init__.py
from lower_level_folder.mainclass import MyClass

creating module in python - how imports work

I'm creating a module in a python app, I have my primary code file, and I want to import some helper methods/classes from a helper folder. This is what I have for my folder structure:
module:
__init__.py
helpers:
__init__.py
some_class.py
this is module/helpers/__init__.py file:
from .some_class import SomeClass
def helper_method_1():
# code
def helper_method_2():
# code
so my question is: is importing SomeClass inside module/helpers/__init__.py inside the helpers enough to use it as in import in my main module/__init.py file?
this is what I'm trying in my module/__init__.py
from .helpers import (SomeClass, helper_method_1, helper_method_2)
I'm kind of in the middle of doing a bunch of things, so can't test it for errors at the moment
Yes, it is enough.
Unless module has __all__ variable, all names (including names imported from other modules) are exported.

How to import everything inside a folder into a single module in Python2

I simply want to take all my .py files from a single folder (I don't care about the sub-folders for now) and put them into a single module.
The use case I'm having here is that I'm writing some pretty standard object-oriented code and I'm using a single file for every class, and I don't want to have to write from myClass import myClass for every class into my __init__.py. I can't use Python3, so I'm still working with impand reloadand such.
At the moment I'm using
# this is __init__.py
import pkgutil
for loader, name, is_pkg in pkgutil.walk_packages(__path__):
if not is_pkg:
__import__(__name__ + "." + name)
and it doesn't seem to work, it includes the packages but it includes them as modules, so that I have to write MyClass.MyClass for a class that is defined in a file with it's own name. That's silly and I don't like it.
I've been searching forever and I'm just getting more confused how complicated this seemingly standard use case seems to be. Do python devs just write everything into a single file? Or do they always have tons of imports?
Is this something that should be approached in an entirely different way?
What you really want to do
To do the job you need to bind your class names to namespace of your __init__.py script.
After this step you will be able to just from YourPackageName import * and just use your classes directly. Like this:
import YourPackageName
c = YourPackageName.MyClass()
or
from YourPackageName import *
c = MyClass()
Ways to achieve this
You have multiple ways to import modules dynamically: __import__(), __all__.
But.
The only way to bind names into namespace of current module is to use from myClass import myClass statement. Static statement.
In other words, content of each of your __init__.py scripts should be looking like that:
#!/usr/bin/env python
# coding=utf-8
from .MySubPackage import *
from .MyAnotherSubPackage import *
from .my_pretty_class import myPrettyClass
from .my_another_class import myAnotherClass
...
And you should know that even for a dynamic __all__:
It is up to the package author to keep this list up-to-date when a new version of the package is released.
(https://docs.python.org/2/tutorial/modules.html#importing-from-a-package)
So a clear answers to your questions:
Do python devs just write everything into a single file?
No, they don't.
Or do they always have tons of imports?
Almost. But definitely not tons. You need to import each of your modules just once (into an appropriate __init__.py scripts). And then just import whole package or sub-package at once.
Example
Let's assume that there is next package structure:
MyPackage
|---MySubPackage
| |---__init__.py
| |---pretty_class_1.py
| |---pretty_class_2.py
|---__init__.py
|---sleepy_class_1.py
|---sleepy_class_2.py
Content of the MyPackage/MySubPackage/__init__.py:
#!/usr/bin/env python
# coding=utf-8
from .pretty_class_1 import PrettyClass1
from .pretty_class_2 import PrettyClass2
Content of the MyPackage/__init__.py:
#!/usr/bin/env python
# coding=utf-8
from .MySubPackage import *
from .sleepy_class_1 import SleepyClass1
from .sleepy_class_2 import SleepyClass2
As result, now we are able to write next code in our application:
import MyPackage
p = MyPackage.PrettyClass1()
s = MyPackage.SleepyClass2()
or
from MyPackage import *
p = PrettyClass1()
s = SleepyClass2()

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

Categories