python - absolute import for module in the same directory - python

I have this package:
mypackage/
__init__.py
a.py
b.py
And I want to import things from module a to module b, does it make sense to write in module b
from mypackage.a import *
or should I just use
from a import *
Both options will work, I'm just wondering which is better (the 2nd makes sense because it's in the same level but I'm considering the 1st to avoid collisions, for example if the system is running from a folder that contains a file named a.py).

You can safely use number 2 because there shouldn't be any collisions - you'll be always importing a module from the same package as the current one. Please note, that if your module has the same name as one of the standard library modules, it will be imported instead of the standard one. From the documentation:
When a module named spam is imported, the interpreter first searches
for a built-in module with that name. If not found, it then searches
for a file named spam.py in a list of directories given by the
variable sys.path. sys.path is initialized from these locations:
the directory containing the input script (or the current directory).
PYTHONPATH (a list of directory names, with the same syntax as the
shell variable PATH).
the installation-dependent default.
After initialization, Python programs can modify sys.path. The
directory containing the script being run is placed at the beginning
of the search path, ahead of the standard library path. This means
that scripts in that directory will be loaded instead of modules of
the same name in the library directory. This is an error unless the
replacement is intended. See section Standard Modules for more
information.
The option from mypackage.a import * can be used for consistency reasons all over the project. In some modules you will have to do absolute imports anyway. Thus you won't have to think whether the module is in the same package or not and simply use a uniform style in the entire project. Additionally this approach is more reliable and predictable.
Python style guidelines don't recommend using relative imports:
Relative imports for intra-package imports are highly discouraged.
Always use the absolute package path for all imports. Even now that
PEP 328 is fully implemented in Python 2.5, its style of explicit
relative imports is actively discouraged; absolute imports are more
portable and usually more readable.
Since python 2.5 a new syntax for intra-package relative imports has been introduced. Now you can . to refer to the current module and .. referring to the module being 1 level above.
from . import echo
from .. import formats
from ..filters import equalizer

You should use from mypackage.a import things, you, want.
There are two issues here, the main one is relative vs absolute imports, the semantics of which changed in Python 3, and can optionally be used in Python 2.6 and 2.7 using a __future__ import. By using mypackage.a you guarantee that you will get the code you actually want, and it will work reliably on future versions of Python.
The second thing is that you should avoid import *, as it can potentially mask other code. What if the a.py file gained a function called sum? It would silently override the builtin one. This is especially bad when importing your own code in other modules, as you may well have reused variable or function names.
Therefore, you should only ever import the specific functions you need. Using pyflakes on your sourcecode will then warn you when you have potential conflicts.

Related

Python package cannot be imported

I have a Python module called util. I would like to import a script in this package _util.py from another script in scripts folder.
Even if the util package has an empty __init__.py file it does not appear as a Python package but a normal directory, without the small dot on folder image.
How can I import this module?
A preliminary answer to your question is that modules or methods beginning with underscores are meant to be used internally.
_my_method() should only be referenced from within the module holding it
_my_module() should only be referenced from within the package holding it
That being said, this convention is meant to be a hint to other developers, not a strict prohibition. Perhaps the first step you can take to solve the import issue is to rename _util.py to util.py and proceed from there.

Python 2 relative imports: two different packages needs a common class

So I have thought about it this way for a Python 2.7 project. It would be composed of two independent parts requiring a common class (module) file in a third package:
SomeRootFolder/Package1Folder/manyPythonModuleFiles.py
SomeRootFolder/Package2Folder/manyPythonModuleFiles.py
SomeRootFolder/SharedPackageFolder/OneCommonClassNeedsToBeShared.py
What I want to do is to import the common class in the shared package from both packages. The two first packages do not require to interact together but needs that one class. The python programs might be runned with the console opened from within the two package folders themselves, such as:
cd Package1Folder
python SomeMainFile.py
If it is easier, the Python call could be like python Package1Folder/SomeMainFile.py but I need to plan this.
Could you provide how I could do the relative imports from package 1 or 2 for a file in the third shared package? Do I need an __init__.py file in the SomeRootFolder folder? I am always confused by relative imports and those import standards and syntax that are different between Python 2 and 3. Also could you validate to me that this is an acceptable way to proceed? Any other ideas?
Thanks all!
If you want to use relative imports,you need __init__.py in SharedPackageFolder folder,and you can use this to import OneCommonClassNeedsToBeShared.py:
from ..SharedPackageFolder import OneCommonClassNeedsToBeShared
See more details about Rationale for Relative Imports .
With the shift to absolute imports, the question arose whether
relative imports should be allowed at all. Several use cases were
presented, the most important of which is being able to rearrange the
structure of large packages without having to edit sub-packages. In
addition, a module inside a package can't easily import itself without
relative imports.
Also you can use absolute imports,relative imports are no longer strongly discouraged,using absolute_import is strongly suggested in some case.
You need to make sure SomeRootFolder is in your PYTHONPATH,or make this folder as sources root,it's more easier for you to import package or scripts in your large project,but sometimes you should be careful with absolute imports.
from SharedPackageFolder import OneCommonClassNeedsToBeShared.py
Absolute imports. From PEP 8:
Relative imports for intra-package imports are highly discouraged. Always use the absolute package path for all imports. Even now that
PEP 328 [7] is fully implemented in Python 2.5, its style of explicit
relative imports is actively discouraged; absolute imports are more
portable and usually more readable.
By the way,relative imports in Python 3 might return SystemError,have a look at Question:Relative imports in Python 3.
#vaultah offers some solutions,they might be helpful.
Hope this helps.

Importing From Sister Subdirectories in Python?

So, I've seen a few similar questions on Stack Overflow, but nothing seems to address my issue, or the general case. So, hopefully this question fixes that, and stops my headaches. I have a git repo of the form:
repo/
__init__.py
sub1/
__init__.py
sub1a/
__init.py
mod1.py
sub2/
__init__.py
mod2.py
How do I import mod2.py from mod1.py and vice versa, and how does this change depending on whether mod1.py or mod2.py are scripts (when each respectively is importing-- not being imported)?
The simplest solution is to put the directory containing repo in your PYTHONPATH, and then just use absolute-path imports, e.g. import repo.sub2.mod2 and so on.
Any other solution is going to involve some hackery if you want it to cover cases where you're invoking both the python files directly as scripts from arbitrary directories - most likely sys.path mangling to effectively accomplish the same thing as setting PYTHONPATH, but without having to have the user set it.
If you are using Python 2.6+, you have two choices:
Relative imports
Adding repo to your PYTHONPATH
With relative imports, a special dot syntax is used:
in package sub1:
from .sub2.mod2 import thing
in package sub1a:
from ..sub2.mod2 import otherthing
Note that plain import statements (import module) don't work with relative imports.
A better solution would be using absolute imports with your Python path set correctly (example in bash):
export PYTHONPATH=/where/your/project/is:$PYTHONPATH
More info:
How to do relative imports in Python?
Permanently add a directory to PYTHONPATH
Import a module from a relative path
A script or module can import modules that are either
on the system path, or
part of the same package as the importing script/module.
For modules these rules apply without exception. For scripts, the rules apply, but the wrinkle is that by default when you run a script, it is not considered to be part of a package.
This means that by default a script can only import modules that are on the system path. By default the path includes the current directory, so if you run a script, it can import modules in the same directory, or packages that are subdirectories. But that's it. A script has no notion of "where it is" in the directory tree, so it can't do any imports that require specific relative path information about enclosing directories. That means you cannot import things "from the parent directory" or "from a sibling directory". Things that are in those directories can only be imported if they are on the system path.
If you want to make a script "know" that is in a package, you can give it a __package__ attribute. See this previous question. You can then use explicit relative imports (e.g., from ...sub2 import mod2) normally from within that script.

Python modules with identical names (i.e., reusing standard module names in packages)

Suppose I have a package that contains modules:
SWS/
__init.py__
foo.py
bar.py
time.py
and the modules need to refer to functions contained in one another. It seems like I run into problems with my time.py module since there is a standard module that goes by the same name.
For instance, in the case that my foo.py module requires both my SWS.time and the standard python time modules, I run into trouble since the interpreter will look inside the package and find my time.py modules before it comes across the standard time module.
Is there any way around this? Is this a no-no situation and should modules names not be reused?
Any solutions and opinions on package philosophy would be useful here.
Reusing names of standard functions/classes/modules/packages is never a good idea. Try to avoid it as much as possible. However there are clean workarounds to your situation.
The behaviour you see, importing your SWS.time instead of the stdlib time, is due to the semantics of import in ancient python versions (2.x). To fix it add:
from __future__ import absolute_import
at the very top of the file. This will change the semantics of import to that of python3.x, which are much more sensible. In that case the statement:
import time
Will only refer to a top-level module. So the interpreter will not consider your SWS.time module when executing that import inside the package, but it will only use the standard library one.
If a module inside your package needs to import SWS.time you have the choice of:
Using an explicit relative import:
from . import time
Using an absolute import:
import SWS.time as time
So, your foo.py would be something like:
from __future__ import absolute_import
import time
from . import time as SWS_time
It depends on what version of Python you're using. If your targeted Python version is 2.4 or older (in 2015, I sure hope not), then yes it would be bad practice as there is no way (without hacks) to differentiate the two modules.
However, in Python 2.5+, I think that reusing standard lib module names within a package namespace is perfectly fine; in fact, that is the spirit of PEP328.
As Python's library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It's a particularly difficult problem inside packages because there's no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path . This is called an absolute import.
The python-dev community chose absolute imports as the default because they're the more common use case and because absolute imports can provide all the functionality of relative (intra-package) imports -- albeit at the cost of difficulty when renaming package pieces higher up in the hierarchy or when moving one package inside another.
Because this represents a change in semantics, absolute imports will be optional in Python 2.5 and 2.6 through the use of from __future__ import absolute_import
SWS.time is clearly not the same thing as time and as a reader of the code, I would expect SWS.time to not only use time, but to extend it in some way.
So, if SWS.foo needs to import SWS.time, then it should use the absolute path:
# in SWS.foo
# I would suggest renaming *within*
# modules that use SWS.time so that
# readers of your code aren't confused
# with which time module you're using
from SWS import time as sws_time
Or, it should use an explicit relative import as in Bakuriu's answer:
# in SWS.foo
from . import time as sws_time
In the case that you need to import the standard lib time module within the SWS.time module, you will first need to import the future feature (only for Python 2.5+; Python 3+ does this by default):
# inside of SWS.time
from __future__ import absolute_import
import time
time.sleep(28800) # time for bed
Note: from __future__ import absolute_imports will only affect import statements within the module that the future feature is imported and will not affect any other module (as that would be detrimental if another module depends on relative imports).
As others have said, this is generally a bad idea.
That being said, if you're looking for potential workarounds, or a better understanding of the problem, I suggest you read the following SO questions:
Importing from builtin library when module with same name exists
How to access a standard-library module in Python when there is a local module with the same name?
Yeah, really no good way around it. Try not to name your modules like standard packages. If you really want to call your module time, i'd recommend using _time.py instead. Even if there was a way to do it, it would make your code hard to read and confusing when it came to the 2 time modules.

Should I use "from package import utils, settings" or "from . import utils, settings"

I'm developing a Python application; it has all its code in one package and runs inside this of course. The application's Python package is of no interest from the interpreter to the user, it's simply a GUI application.
The question is, which style is preferred when importing modules inside the application package
from application import settings, utils
or
from . import settings, utils
That is I can either specify the name as it is (here 'application') or I can say "current package" by using "."
This is a Free software package so the possibility exists that someone wants to make a fork of my application and change its name. In that case, alternative 1 is a slight nuisance. Still, I use style 1 all the time (although early code uses style 2 in some places), since style 1 looks much better.
Are there any arguments for my style (1) that I have missed? Or is it stupid not to go with style 2?
The Python Style Guide recommends explicitly against relative imports (the . style):
Relative imports for intra-package imports are highly discouraged.
Always use the absolute package path for all imports.
Even now that PEP 328 [7] is fully implemented in Python 2.5,
its style of explicit relative imports is actively discouraged;
absolute imports are more portable and usually more readable.
I tend to agree. Relative imports mean the same module is imported in different ways in different files, and requires that I remember what I'm looking at when reading and writing. Not really worth it, and a rename can be done with sed.
Besides the issue of renaming, the only problem with absolute imports is that import foo might mean the top-level module foo or a submodule foo beneath the current module. If this is a problem, you can use from __future__ import absolute_import; this is standard in Python 3.

Categories