How can I import all files under subdir in python - python

I have dir structure like this:
Proj/
run.py
Util/
__init__.py
x.py
y.py
In x.py, I define a function:
def p():
return 1
In y.py, I define:
def q():
return 2
Currently in run.py, I'll use
from Util import *
But I have to call them using
x.p()
y.q()
But I want to call them using
p()
q()
Is there a way that I can do that? Like (as I imagine)
from Util.* import *

Bring the names up into the package namespace, by using star imports in the __init__.py:
# in util/__init__.py
from util.x import *
from util.y import *
In each submodule, define the names which you want to export by using the __all__ name:
# in x.py
__all__ = ['p']
And:
# in y.py
__all__ = ['q']
This is a pretty standard usage of the __init__.py module within a package, documented here.

Related

How to fix name is not defined in Python

I am running a python project like this:
project
Test.py
COMMON.py
SYSTEM.py
PTEST1
Hello.py
when run the code "Test.py" it will show NameError, I am not sure why?
But if I replaced the "from SYSTEM import *" with "from COMMON import *" in Test.py and PTEST1/Hello.py, it works as expect.
#Test.py is like this:
from SYSTEM import *
myvalue.Hello.printf()
# COMMON.py is like this:
myvalue = lambda: None
from PTEST1.Hello import Hello
myvalue.Hello = Hello
# SYSTEM.py is like this:
from COMMON import *
#PTEST1/Hello.py
from SYSTEM import *
class Hello():
#staticmethod
def printf():
print("Hello1")
print(vars(myvalue))
I expect there is no "NameError" by not changing import code. BTW, my python is 3.6+
Good practice is to give filenames in lowercase.
It looks like you are creating a Python project under project/. Any directory needs to have a file __init__.py in every directory in order for it to be discovered in Python.
You then need to refer to modules by their full name (not relative naming).
So the directory structure should be:
project/
__init__.py
test.py
common.py
system.py
ptest1/
__init__.py
hello.py
Every time you refer to file you should give the full path.
# import everything from hello.py
from project.ptest1.hello import *
# import everything from common.py
from project.common import *
# import everything from system.py
from project.system import *

How to import only functions in a script with custom package/module in Python?

I'm building a package and a noticed that when I import the submodules, they include all of the built-ins that I've imported as well. Is there a way to get around this so when I navigate the submodule with tab complete only the functions and objects from the script are present?
For example, when I import examplemodule.submodule to only see function_i_want when I'm navigating the package contents?
Directory structure
examplemodule
| __init__.py
| submodule
| __init__.py
| submodule.py
examplemodule | submodule | submodule.py
from collections import *
def function_i_want():
return True
Here's an example of what I can import from the module:
>>> import examplemodule
>>> from examplemodule import submodule
>>> submodule.
submodule.AsyncGenerator( submodule.MappingView(
submodule.AsyncIterable( submodule.MutableMapping(
submodule.AsyncIterator( submodule.MutableSequence(
submodule.Awaitable( submodule.MutableSet(
submodule.ByteString( submodule.OrderedDict(
submodule.Callable( submodule.Reversible(
submodule.ChainMap( submodule.Sequence(
submodule.Collection( submodule.Set(
submodule.Container( submodule.Sized(
submodule.Coroutine( submodule.UserDict(
submodule.Counter( submodule.UserList(
submodule.Generator( submodule.UserString(
submodule.Hashable( submodule.ValuesView(
submodule.ItemsView( submodule.defaultdict(
submodule.Iterable( submodule.deque(
submodule.Iterator( submodule.function_i_want(
submodule.KeysView( submodule.namedtuple(
submodule.Mapping( submodule.submodule
When you say from x.y import * you are importing everything defined in __all__ from the module y that resides in directory x.
If you'd only like to import a subset of y you can do the following:
Limit what you're importing from your script
from examplemodule.submodule import function_i_want
or
from examplemodule.submodule import (
function_i_want,
other_function_i_want
)
Define __all__ in your __init__.py
__all__ = ['function_i_want', 'other_function_i_want']
what you could do is import just the module e.g.
import examplemodule
examplemodule.submodule
what this does is only calls the function if you write the module first then .submodule. this is also good if you have more than one module

Python - Retrieve all of the functions under multiple classes in a package

I currently have a package structure like that:
common/
a.py
b.py
c.py
__init__.py
.svn
util/
util.py
__init__.py
I want to write a function in util.py to retrieve all of the functions in a.py, b.py, c.py
from os import listdir
files = listdir(directory_to_common)
for f in files:
if '.py' in f and '__' not in f:
module_name = f.split(.)[0]
module = __import__(module_name)
I can successfully import the module.
Than I used
inspect.getmembers(module)
but it returns a lot of un-needed information.
From here, how do I retrieve the functions inside a.py, b.py, c.py?
#a.py, b.py, c.py has similar structure as follows:
class A:
def __init__(self):
.....
def method1_in_a(self):
.....
def method2_in_a(self):
.....
To return only needed information, use the optional argument predicate. Example to find all classes in a module and all functions in a class:
classes = inspect.getmembers(module, predicate=inspect.isclass)
for cls_name, cls in classes:
functions = inspect.getmembers(cls, predicate=inspect.isfunction)
for fn_name, fn in functions:
print(cls_name, fn_name)
For a list of all available predicates, see inspect module docs (all the functions named inspect.isXYZ are predicates).
You can try this:
import inspect
from os import listdir
files = listdir(directory_to_common)
functions = [inspect.getmembers(__import__("{}.{}".format(directory_to_common, i[:-3])), inspect.isfunction) for i in files if i.endswith('.py') and not i.startswith('__')]

How to perform a dynamic relative import in Python 3?

I have a following file structure:
mymodule/
__init__.py
mylib.py
test.py
File mymodule/__init__.py:
# mymodule/__init__.py
def call_me():
module = __import__('.mylib')
module.my_func()
File mymodule/mylib.py:
# mymodule/mylib.py
def my_func():
print("hi!")
File test.py:
# test.py
from mymodule import call_me
call_me()
If I run python3 test.py it fails with the error:
module = __import__('.mylib')
ImportError: No module named '.mylib'
I want to perform a relative import inside of call_me that equals to the static import from . import mylib. How can I do it?
Use importlib.import_module and specify your package from __name__ in __init__.py:
importlib.import_module(name, package=None)
Import a module.
The 'package' argument is required when performing a relative import. It
specifies the package to use as the anchor point from which to resolve the
relative import to an absolute import.
Example:
import importlib
def call_me():
module = importlib.import_module('.mylib', package=__name__)
module.my_func()
How about this,
def call_me():
mylib = __import__('mylib', globals(), locals(), [], 1)
mylib.my_func()
Please refer the doc: import

How to expose every name in sub-module in __init__.py of a package?

I defined a package that include a dynamically growing set of modules:
- mypackage
- __init__.py
- module1.py
- module2.py
- module3.py
... many more .py files will be added
I could expose every name in every module in __init__.py like this:
from module1 import *
from module2 import *
from module3 import *
Now when I import mypackage in client code, I get all the names defined in the sub-modules:
# suppose funcA is defined in module1, class B is defined in module2
import mypackage
mypackage.funcA() # call module1.funcA
b = mypackage.B() # module2.B
The problem is, I could define many new modules in mypackage, and I don't want to add an extra line from modulex import * to __init__.py, every time I add a new module to the package.
What is the best way to dynamically export names in all submodules?
In Python 3 the solution is straightforward using importlib and pkgutil.
Placing the following code in __init__.py is the same typing from submodule import * for all submodules (even nested ones).
import importlib
import pkgutil
for mod_info in pkgutil.walk_packages(__path__, __name__ + '.'):
mod = importlib.import_module(mod_info.name)
# Emulate `from mod import *`
try:
names = mod.__dict__['__all__']
except KeyError:
names = [k for k in mod.__dict__ if not k.startswith('_')]
globals().update({k: getattr(mod, k) for k in names})
If you only want to include immediate submodules (e.g. pkg.mod but not pkg.mod.submod), replace walk_packages with iter_modules.
I emulated from mod import * based on this answer: How to do from module import * using importlib?
I'm not sure if this is what you mean:
but if i've understood correctly - do this in your __init__.py file.
import os
__all__ = []
for module in os.listdir(os.path.dirname(__file__)):
if module != '__init__.py' and module[-3:] == '.py':
__all__.append(module[:-3])
You're adding all files in the same package into the __all__
Simply adding module names to __all__ will not always serve the purpose. I came across such an issue and also required them to be imported in addition to adding them to __all__. This is the code I came up with to make it work in my case. I didn't have any sub packages, so this code works only at the top level.
modules = glob.glob(os.path.dirname(__file__) + '/*.py')
__all__ = []
for mod in modules:
if not str(mod).endswith('__init__.py'):
package_prefix = __name__ + '.'
module_name = str(mod)[str(mod).rfind('\\') + 1:-3]
__all__.append(module_name)
__import__(package_prefix + module_name, globals(), locals(), [''])

Categories

Resources