I have a file structure like this:
/package/main.py
/package/__init__.py
/package/config_files/config.py
/package/config_files/__init__.py
I'm trying to dynamically import config.py from main.py based on a command line argument, something like this:
#!/usr/bin/env python
from importlib import import_module
cmd_arguments = sys.argv
config_str = cmd_arguments[1]
config = import_module(config_str, 'config_files')
but it complains breaks with ModuleNotFoundError: No module named 'default_config'. Similar code in ipython does not suffer the same issue, when called from /package
If there is a better way to load a package at run time via user input, I'm open to suggestions.
You are trying to import from a nested package, so use the full package name:
config = import_module(config_str, 'package.config_files')
Alternatively, use a relative import, and set the second argument to package:
config = import_module('.config_files.{}'.format(config_str), 'package')
This is more secure, as now the config_str string can't be used to 'break out' of the config_files sub package.
You do want to strip dots from user-provided names (and, preferably, limit the name to valid Python identifiers only).
Related
I am making a script (python) and need to import other files (complete).
The file I would like to import, is 2 directories up from the script.
Normal in Python you would do something like
../../../file.py <-- goes up 3 directories
When I do this in Python it gives a syntax error.
..file for example works but as soon as I chain it ../..file.py the syntax error comes in.
I tried
../..file
../../file
/../..file
/../../file
The error says invalid syntax.
The complete command is
from ../..file import *
I would like to import all the content of the file.
The path needs to be relative due to the nature of the script. No hardcoding allowed.
How can I go up multiple directories in Python?
importlib was added to Python 3 to programmatically import a module.
import importlib
moduleName = input('Enter module name:')
importlib.import_module(moduleName)
The .py extension should be removed from moduleName. The function also defines a package argument for relative imports.
If you want to import the whole file you can just do import file. Then you can choose the function that you are interesting in.
for example:
import FULL_PATH_TO_MY_FILE
my_file.my_func...
or you can try:
from FULL_PATH_TO_MY_FILE import *
and then you can use each function in your file like this - myfunc()
I have a requirement where I need to parse the functions defined in a python file from another python file.
e.g. I have a python file with following contents:
a.py
import os, sys
def function1('text'):
pass
def function2('text'):
pass
Another file is:
b.py
interested_func = 'function2'
function_list = <code to fetch the functions defined in a.py>
if interested_func in function_list:
print 'match found'
How can I get the functions from a.py into b.py so that I can compare the same with the 'interested_func' data and can do specific task based on the match.
Please note that I have 100s of files with different functions defined inside them, so I do not want to import the file.
Please help, thanks in advance!
You should probably use the importlib module:
import importlib
obj = importlib.import_module(module)
print(dir(obj))
You can read more about importlib over in the Python docs.
If that doesn't work for you, then you'll probably want to look at some static code analysis tools such as pylint that might give you a clue into how to do this sort of thing. Another place to look would be to check out PyDev's source code and see how it does code analysis.
I am trying to import modules dynamically in Python. Right now, I have a directory called 'modules' with two files inside; they are mod1.py and mod2.py. They are simple test functions to return time (ie. mod1.what_time('now') returns the current time).
From my main application, I can import as follows :
sys.path.append('/Users/dxg/import_test/modules')
import mod1
Then execute :
mod1.what_time('now')
and it works.
I am not always going to know what modules are available in the dirctory. I wanted to import as follows :
tree = []
tree = os.listdir('modules')
sys.path.append('/Users/dxg/import_test/modules')
for i in tree:
import i
However I get the error :
ImportError: No module named i
What am I missing?
The import instruction does not work with variable contents (as strings) (see extended explanation here), but with file names. If you want to import dynamically, you can use the importlib.import_module method:
import importlib
tree = os.listdir('modules')
...
for i in tree:
importlib.import_module(i)
Note:
You can not import from a directory where the modules are not included under Lib or the current directory like that (adding the directory to the path won't help, see previous link for why). The simplest solution would be to make this directory (modules) a package (just drop an empty __init__.py file there), and call importlib.import_module('..' + i, 'modules.subpkg') or use the __import__ method.
You might also review this question. It discusses a similar situation.
You can achieve something like what you are proposing, but it will involve some un-pythonic code. I do not recommend doing this:
dynamic_imports = dict()
for filename in tree:
name = filename.replace('.py', '')
dynamic_imports[name] = __import__(name)
I have a program that creates a module called "cool" using file operations. I later say import cool and then uses the cool module that was created.
Here is my directory
project/
main.py
modules/
maker.py
cool/ #this folder and its contents was made by maker.py
__init__.py
coolm.py
If I want to make my program into the .exe format, this strategy will not work anymore. Does anyone know another technique?
Note: I cannot use exec to use the cool module..
Import your module when you need it like this:
coolmod = __import__('coolm')
coolm.someproperty
Alternatively you could try:
import importlib
coolmod = importlib.import_module('coolm', 'cool')
This allows you to specify the package name as a second argument.
I'm using python and virtualenv/pip. I have a module installed via pip called test_utils (it's django-test-utils). Inside one of my django apps, I want to import that module. However I also have another file test_utils.py in the same directory. If I go import test_utils, then it will import this local file.
Is it possible to make python use a non-local / non-relative / global import? I suppose I can just rename my test_utils.py, but I'm curious.
You can switch the search order by changing sys.path:
del sys.path[0]
sys.path.append('')
This puts the current directory after the system search path, so local files won't shadow standard modules.
My problem was even more elaborate:
importing a global/site-packages module from a file with the same name
Working on aero the pm recycler I wanted access to the pip api, in particular pip.commands.search.SearchCommand from my adapter class Pip in source file pip.py.
In this case trying to modify sys.path is useless, I even went as far as wiping sys.path completely and adding the folder .../site-packages/pip...egg/ as the only item in sys.path and no luck.
I would still get:
print pip.__package__
# 'aero.adapters'
I found two options that did eventually work for me, they should work equally well for you:
using __builtin__.__import__() the built-in function
global_pip = __import__('pip.commands.search', {}, {}, ['SearchCommand'], -1)
SearchCommand = global_pip.SearchCommand
Reading the documentation though, suggests using the following method instead.
using importlib.import_module() the __import__ conv wrapper.
The documentation explains that import_module() is a minor subset of functionality from Python 3.1 to help ease transitioning from 2.7 to 3.1
from importlib import import_module
SearchCommand = import_module('pip.commands.search').SearchCommand
Both options get the job done while import_module() definitely feels more Pythonic if you ask me, would you agree?
nJoy!
I was able to force python to import the global one with
from __future__ import absolute_import
at the beginning of the file (this is the default in python 3.0)
You could reset your sys.path:
import sys
first = sys.path[0]
sys.path = sys.path[1:]
import test_utils
sys.path = first + sys.path
The first entry of sys.path is "always" (as in "per default": See python docs) the current directory, so if you remove it you will do a global import.
Since my test_utils was in a django project, I was able to go from ..test_utils import ... to import the global one.
Though, in first place, I would always consider keeping the name of local file not matching with any global module name, an easy workaround, without modifying 'sys.path' can be to include global module in some other file and then import this global module from that file.
Remember, this file must be in some other folder then in the folder where file with name matching with global module is.
For example.
./project/root/workarounds/global_imports.py
import test_utils as tutil
and then in
./project/root/mycode/test_utils.py
from project.root.workarounds.global_imports import tutil
# tutil is global test_utils
# you can also do
from project.root.workarounds.global_imports import test_utils