I am following this example on how to package a python module. But installing my built package with pip, when I tried to use it, while the following works.
from towel_stuff import towel_utils
x = towel_utils.has_towel()
print(x)
And this also works,
import towel_stuff.towel_utils
x = towel_stuff.towel_utils.has_towel()
print(x)
I don't understand, why the following doesn't work.
import towel_stuff
x = towel_stuff.towel_utils.has_towel()
print(x)
Normally, for example if we want to use os.path, we don't need to write import os.path, but just import os is enough. So, with my built package, why do I have to give the full package path?
Of course I can use from towel_stuff import * to import everything, but was just curious why we don't need to give the full path for standard packages.
Given the following structure:
towel_stuff
----__init__.py
----towel_utils
When you use import towel_stuff, the only file executed is __init__.py, so if you haven't imported towel_utils in __init__.py, it is not accessible at all.
So in short, when you use import a_module, you are and only are executing the __init__.py file in that module directory. If you want to access the a_module.file, you need to explicitly import it.
When you use import a_file, you are executing that file, as path is just a variable of os, so you can access it like os.path.
So the difference is, path is a variable in os while towel_utils is a submodule in towel_stuff. Or let's say path is an imported module in os which makes it become a variable.
Normally, for example if we want to use os.path, we don't need to write import os.path, but just import os is enough. So, with my built package, why do I have to give the full package path?
It all depends on how the module is constructed. For example, if in your towel_stuff module you included:
from towel_stuff import towel_utils
Then code that imported only towel_stuff would have access to towel_stuff.towel_utils without additional imports.
Related
I have spent so many hours trying out different answers on stack overflow that i no longer know what exactly is the proper way to use relative imports. Keep in mind this import should work on localhost and on a server
My project structure
init.py
Attempts to import Authenticate class in main.py result into ImportError: attempted relative import with no known parent package
Kindly give an explanation or links with working examples of importing in the same directory.
You are trying to import a Jupyter Notebook, not a class. This is why you get the ImportError.
Have a look at this: ipynb import another ipynb file
If you do not want to import from a Jupyter Notebook but from a module in a specified path you can try this:
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
You can also use relative import:
from foo import bar
Another option is to add a path to sys.path (over using import) to simplify things when importing more than one module from a single package:
import sys
# my_package dir contains mod_one.py, mod_two.py and mod_three.py
sys.path.append('/foo/bar/my_package')
from mod_one import foo
from mod_two import bar
from mod_three import foobar
I have two file
foo.py
main.py
while executing python main.py, I want main.py to import foo.py.
I tried
from . import foo
But python complains
Attempted relative import beyond top-level package
I also tried
from foo import func_name
It works, but that means I can only directly import what get exposed. I want to use it like foo.func_name
Is it possible to import the whole module in a relative way (regardless what the current working directory is)?
The script directory is already a part of the import path. Simply use
import foo
In Python 3, is there a difference between
import os.path
os.path.join(a,b)
and
import os
os.path.join(a,b)
except that the latter is shorter?
(I know about import os.path as path but I'm talking only about the unnamed import form. I found it in some code and was wondering why it was used)
If a package does not include a module in its __init__.py, then
package.module
will not work even if you have already imported pacakge unless you also do
import package.module
This does not apply to package=os and module=path (os is actually a module (contained in os.py) that imports another module, path somewhere in its code)
I have a python script that is trying to import another script somewhere in the file-system (path is only known at runtime).
To my understanding I need to use the imp module and this might work, but when loading the module I get an error that modules used by the imported module are not found.
Heres the code:
importer.py:
import imp
imp.load_compiled("my_module","full_path_to_my_module\\my_module.pyc")
my_module.py:
import sys
import another_module
When I run importer.py I get htis error message:
ImportError: No module named another_module
Whats going wrong here ?
I suspect that when 'importer.py' is loading 'my_module.pyc' hes also trying to load 'another_module' (thats good) but is looking in the wrong place (eg not 'full_path_to_my_module')
EDIT:
I tried adding 'full_path_to_my_module' to the system path:
import imp
import sys
sys.path.append(full_path_to_my_module)
imp.load_compiled("my_module",full_path_to_my_module+my_module)
But I still get the same error
Maybe I do something thats not necessary - Here's my goal:
I want to be able to use all functionality of 'my_module.pyc' inside 'importer.py'. But the location of 'my_module.pyc' is given as a parameter to 'importer.py'.
imp.load_compiled returns the compiled module object, it is different to the import statement which also binds the module to a name
import imp
my_module = imp.load_compiled("my_module", "full_path_to_my_module/my_module.pyc")
Then you can do something like:
my_module.yayfunctions('a')
Complete example session:
$ cat /tmp/my_module.py
def yayfunctions(a):
print a
$ python -m compileall /tmp/my_module.py
$ ls /tmp/my_module.py*
my_module.py my_module.pyc
$ python
>>> import imp
>>> my_module = imp.load_compiled("my_module", "/tmp/my_module.pyc")
>>> my_module.yayfunctions('a')
a
Edit regarding comment (ImportError: No module named another_module), I assume the error is caused by the code in my_module.pyc, and the another_module.py lives in the same directory
In that case, as others have suggested, it's simpler to just add the directory containing my_module to sys.path and use the regular import mechanism, specifically __import__
Here's a function which should do what you want:
import os
def load_path(filepath):
"""Given a path like /path/to/my_module.pyc (or .py) imports the
module and returns it
"""
path, fname = os.path.split(filepath)
modulename, _ = os.path.splitext(fname)
if path not in sys.path:
sys.path.insert(0, path)
return __import__(modulename)
if __name__ == '__main__':
# Example usage
my_module = load_path('/tmp/my_module.py')
my_module.yayfunctions('test')
It is since at the scope of import another_module your "full_path_to_my_module" isn't known.
Have you tried to add the path to known paths instead, i.e.:
import sys
sys.path.append("full_path_to_my_module")
You don't actually need to use the imp module to load pyc modules.
An easy way to try it out is to make two python modules, one importing from the other and run it. Delete then the imported .py file so you only get the .pyc file left: when running the script the import will work just fine.
But, for importing py files from random directories, you may want to add that directory to the python path first before importing it.
For instance:
import sys
sys.path.insert(0, "/home/user/myrandomdirectory")
Loading pyc files works the exact same way as loading a py file except it doesn't do a compile step. Thus just using import mymodule will work as long as the version number of the pyc is the same as the python you're running. Otherwise you'll get a magic number error.
If you module isn't in your path you'll need to add that to sys -- or if its a subdirectory, add a __init__.py file to that directory..
I have a module foo, containing util.py and bar.py.
I want to import it in IDLE or python session. How do I go about this?
I could find no documentation on how to import modules not in the current directory or the default python PATH.
After trying import "<full path>/foo/util.py",
and from "<full path>" import util
The closest I could get was
import imp
imp.load_source('foo.util','C:/.../dir/dir2/foo')
Which gave me Permission denied on windows 7.
One way is to simply amend your path:
import sys
sys.path.append('C:/full/path')
from foo import util,bar
Note that this requires foo to be a python package, i.e. contain a __init__.py file. If you don't want to modify sys.path, you can also modify the PYTHONPATH environment variable or install the module on your system. Beware that this means that other directories or .py files in that directory may be loaded inadvertently.
Therefore, you may want to use imp.load_source instead. It needs the filename, not a directory (to a file which the current user is allowed to read):
import imp
util = imp.load_source('util', 'C:/full/path/foo/util.py')
You could customize the module search path using the PYTHONPATH environment variable, or manually modify the sys.path directory list.
See Module Search Path documentation on python.org.
Give this a try
import sys
sys.path.append('c:/.../dir/dir2')
import foo
Following phihag's tip, I have this solution. Just give the path of a source file to load_src and it will load it. You must also provide a name, so you can import this module using this name. I prefer to do it this way because it's more explicit:
def load_src(name, fpath):
import os, imp
return imp.load_source(name, os.path.join(os.path.dirname(__file__), fpath))
load_src("util", "../util.py")
import util
print util.method()
Another (less explicit) way is this:
util = load_src("util", "../util.py") # "import util" is implied here
print util.method() # works, util was imported by the previous line
Edit: the method is rewritten to make it clearer.