Dynamic import of several names from a module - python

I am trying to import some symbols from one package into another. I have tried the following, with no luck as both are syntax errors.
from signal import SIG*
or
import _signal
import _re
from signal import [i for i in dir(_signal) if _re.search("^SIG",i)!=None ]
Is there a way to do this.

Use importlib:
import importlib
mod = importlib.import_module('signal')
loc = locals()
for name in dir(mod):
if name.startswith('SIG'):
loc[name] = getattr(mod, name)
del mod, loc, importlib

Related

python3: conditional import from one of two packages

I have two packages fast and slow which are "api compatible" with each other.
If fast is available I want to import from it, else from slow.
My current working solution is
import imp
try:
imp.find_module('fast')
from fast.UtilityFunctions import UtilityFunctions
from fast.Utilities.Log import Log
from fast.model.device_driver import DriverModel
...
except ImportError:
from slow.UtilityFuntions import UtilityFunctions
...
# normal code
It there a better way to write this? Can I eliminate the copy paste job above?
i.e. what would be the pythonic equivalent of this pseudo-code?
import imp
try:
imp.find_module('fast')
alias found=fast
except ImportError
alias found=slow
from found.UtilityFuntions import UtilityFunctions
...
Why don't you just import the modules directly?
try:
import fast as found
except ImportError:
import slow as found
from found.UtilityFuntions import UtilityFunctions
try:
import some_specific_module as module
except ImportError:
import other_module
Try this piece of code!

Python Error : Cannot import name 'Mapping' from 'collections'

When I try to run my project I get this error. I've seen alot of people having this issue on here and I've tried their codes but It didn't work. I'm using Python 3.10.6. Where should I fix to solve it?
Error
ImportError: cannot import name 'Mapping' from 'collections' (/Users/User/.pyenv/versions/3.10.6/lib/python3.10/collections/__init__.py)
init.py
import _collections_abc
import sys as _sys
from itertools import chain as _chain
from itertools import repeat as _repeat
from itertools import starmap as _starmap
from keyword import iskeyword as _iskeyword
from operator import eq as _eq
from operator import itemgetter as _itemgetter
from reprlib import recursive_repr as _recursive_repr
from _weakref import proxy as _proxy
try:
from _collections import deque
except ImportError:
pass
else:
_collections_abc.MutableSequence.register(deque)
try:
from _collections import defaultdict
except ImportError:
pass
Mapping class was introduced in Python 3.3
Try upgrading to a newer version of Python.

How to import module by variable name and how to name said module

So I want to import a python script depending on a variable name. Say I pass this function the module path, I'd like it to import that module from the path I passed and give it a name. Example:
import some_module as sm
#Would import some_module
What I want is something like this
module_to_import = some_other_module
import module_to_import as mti
#Would import some_other_module
Sorry if this doesn't make much sense, was quite difficult to put into words.
Thanks.
with importlib.import_module you could do this:
from importlib import import_module
module_name = 'some_module'
mti = import_module(module_name)
meaning you could import the module from a string. in your case you might get that name from your other module using
module_name = some_other_module.__name__
What you probably are looking for is ability to dynamically import modules
module = __import__(module_name)
my_class = getattr(module, class_name)
instance = my_class()
You can read more about this and alternative solutions at this link

Python cannot import from another file name not defined

I am trying to import a custom function from another python file but keep getting an error NameError: name 'testme' is not defined. I confirmed that I am importing the file correctly according to this SO post and that the function is top level. What else can I try to fix this?
My main python file is:
import sys
import dbconn
#from dbconn import testme #<----did not work
dev=True
if(dev):
categId='528'
pollIds=[529,530,531]
else:
categId=str(sys.argv[1])
pollIds=[529,530,531]
df=testme(categIds)#callServer(categId,pollIds)
df
if(not categId.isdigit):
print('categ id fail. expected digit got: '+categId)
.....
and dbconn.py:
import pymysql #pip3 install PyMySQL
import pandas as pd
from scipy.stats.stats import pearsonr
from scipy import stats
def testme(categIds):
try:
df=categIds
except Exception as e:
print("broke")
return categIds
Not sure if it makes a difference but I am running the main python file from within a Jupyter notebook, and have a compiled version of dbconn.py in the same directory
In response to the suggestions I tried:
df=dbconn.testme(categIds)
got the error:
module 'dbconn' has no attribute 'testme'
You Have to follow these fox exact import
1)import <package>
2)import <module>
3)from <package> import <module or subpackage or object>
4)from <module> import <object>
in your case, you have tried
from dbconn import testme
you have to use only packages in from section and module in import section
like >>
from testme import dbconn

How to import a submodule in Python? (without `exec`)

I would like to import a submodule without knowing its name beforehand,
>>> __import__("os.path")
<module 'os' from '/usr/lib/python3.3/os.py'>
Doesn't work as you might expect, returning os, not os.path.
I came up with this solution.
def import_submodule(mod, submod):
ns = {}
exec_str = "from %s import %s as submod" % (mod, submod)
exec(exec_str, ns, ns)
return ns["submod"]
This gives the result:
>>> import_submodule("os", "path")
<module 'posixpath' from '/usr/lib/python3.3/posixpath.py'>
However I would rather not use exec() because its rather bad practice and seems unnecessary when Pythons import mechanisms are available already through __import__, imp and importlib modules.
Is there a way in Python3.x to do this kind of import though a function call, rather then using exec() ?
Use importlib.import_module:
>>> import importlib
>>> importlib.import_module('os.path')
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>
This should work in python2.7+ and 3.1+.
Note that if you want do: from A import B as C as a function call, importlib.import_module won't always work, since B may not be a module.
Heres a function which uses importlib and getattr.
def my_import_from(mod_name, var_name):
import importlib
mod = importlib.import_module(mod_name)
var = getattr(mod, var_name)
return var
So this:
from os.path import dirname as var
Can be replaced with this:
var = my_import_from("os.path", "dirname")
Which avoids exec and allows both submodules and any variables defined in the module.
Since my question explicitly says importing a submodule, the answer from #Bakuriu is correct, however including this for completeness and it may help others who run into the same problem.
Import both parts
As #Marius pointed out in the comment section, what appears as a submodule is not always a submodule.
This is the case with os.path and I encountered the same with lxml.etree.
The trick is to import both parts, i.e. both os and os.path.
Here is what worked for me for sets of modules:
# PyPI imports
import pkg_resources, subprocess, sys
modules = {'lxml.etree', 'pandas', 'screeninfo'}
required = {m.split('.')[0] for m in modules}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed
if missing:
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])
for module in set.union(required, modules):
globals()[module] = __import__(module)
Tests:
print(pandas.__version__)
print(lxml.etree.LXML_VERSION)

Categories