Allow multiple imports from a package while preserving its namespace
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc. -- Thanks, Julian DeMille CEO, demilleTech, LLC This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.
On 26 April 2018 at 14:29, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc.
What are the benefits of this over a simple "import <lib>"? I get that it will mean that *only* the names listed will be accessible as <lib>.<mod>, but I don't see why that's important (and specifically why it's important enough to warrant dedicated syntax). Hiding names in a namespace isn't typically something that Python provides language support for. Paul
Some library authors get pretty pissy about implicit imports at the root On Thu, Apr 26, 2018, 09:37 Paul Moore <p.f.moore@gmail.com> wrote:
On 26 April 2018 at 14:29, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc.
What are the benefits of this over a simple "import <lib>"? I get that it will mean that *only* the names listed will be accessible as <lib>.<mod>, but I don't see why that's important (and specifically why it's important enough to warrant dedicated syntax). Hiding names in a namespace isn't typically something that Python provides language support for.
Paul
-- Thanks, Julian DeMille CEO, demilleTech, LLC This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.
On Thu, 26 Apr 2018 at 19:10 Julian DeMille via Python-ideas < python-ideas@python.org> wrote:
Some library authors get pretty pissy about implicit imports at the root
On Thu, Apr 26, 2018, 09:37 Paul Moore <p.f.moore@gmail.com> wrote:
On 26 April 2018 at 14:29, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc.
What are the benefits of this over a simple "import <lib>"? I get that it will mean that *only* the names listed will be accessible as <lib>.<mod>, but I don't see why that's important (and specifically why it's important enough to warrant dedicated syntax). Hiding names in a namespace isn't typically something that Python provides language support for.
Paul
-- Thanks, Julian DeMille
CEO, demilleTech, LLC
This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited. _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
The following works today: Python 3.6.3 (default, Oct 4 2017, 06:09:15) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin Type "help", "copyright", "credits" or "license" for more information.
import os.path os <module 'os' from '/Users/pradyunsg/.venvwrap/venvs/pip/bin/../lib/python3.6/os.py'> os.path <module 'posixpath' from '/Users/pradyunsg/.venvwrap/venvs/pip/bin/../lib/python3.6/posixpath.py'>
I am not sure what you're asking for here.
The following works today:
Python 3.6.3 (default, Oct 4 2017, 06:09:15) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin Type "help", "copyright", "credits" or "license" for more information.
import os.path os <module 'os' from '/Users/pradyunsg/.venvwrap/venvs/pip/bin/../lib/python3.6/os.py'> os.path <module 'posixpath' from '/Users/pradyunsg/.venvwrap/venvs/pip/bin/../lib/python3.6/posixpath.py'>
I am not sure what you're asking for here.
os.path is a very special case. First at all there are no the os/path.py file...
On 26 April 2018 at 23:37, Paul Moore <p.f.moore@gmail.com> wrote:
On 26 April 2018 at 14:29, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc.
What are the benefits of this over a simple "import <lib>"?
Forcing submodule imports would be the main thing, as at the moment, you have to choose between repeating the base name multiple times (once per submodule) or losing the hierarchical namespace. So where: from pkg import mod1, mod2, mod3 bind "mod1", "mod2", and "mod3" in the current namespace, you might instead write: from pkg import .mod1, .mod2, .mod3 to only bind "pkg" locally, but still make sure "pkg.mod1", "pkg.mod2" and "pkg.mod3" all resolve at import time. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
That's the kind of thing I'm looking for. I've dealt with some library authors who were highly against importing the root allowing me to access submodules with hierarchy. On Thu, Apr 26, 2018 at 9:51 AM Nick Coghlan <ncoghlan@gmail.com> wrote:
On 26 April 2018 at 23:37, Paul Moore <p.f.moore@gmail.com> wrote:
On 26 April 2018 at 14:29, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
I personally would like a feature where instead of doing `from ... import ...` (which imports the specified items into the current namespace), one could use something along the lines of `import <lib>.{ <mod1>, <mod2>, ... }` such that the imported modules/attributes could be accessed as `<lib>.<mod1>`, etc.
What are the benefits of this over a simple "import <lib>"?
Forcing submodule imports would be the main thing, as at the moment, you have to choose between repeating the base name multiple times (once per submodule) or losing the hierarchical namespace.
So where:
from pkg import mod1, mod2, mod3
bind "mod1", "mod2", and "mod3" in the current namespace, you might instead write:
from pkg import .mod1, .mod2, .mod3
to only bind "pkg" locally, but still make sure "pkg.mod1", "pkg.mod2" and "pkg.mod3" all resolve at import time.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
-- Thanks, Julian DeMille CEO, demilleTech, LLC This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.
On Thu, Apr 26, 2018 at 11:53 PM, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
That's the kind of thing I'm looking for. I've dealt with some library authors who were highly against importing the root allowing me to access submodules with hierarchy.
With a package, having automatic imports forces those submodules to be loaded eagerly (as soon as you import the package, you load up those modules). Lazily-loaded submodules can improve performance if you don't always need them. +0 for an easier way to import multiple submodules at once. It's not something I've personally had a need for, but it's a sane and logical thing to do. ChrisA
I just ran into a similar problem, how to relatively import without binding the submodule. Let's say you have this : myapp/ urls.py views/ base.py When you're in urls.py and you want to relatively access Functions from base.py, you must use the from syntax. from .views import base base.func() But what if I just want "views" in my namespace? from . import views from .views import base views.base.func() base.func() import myapp.views.base myapp.views.base.func() from . import views import myapp.views.base views.base.func() myapp.views.base.func() Le jeu. 26 avr. 2018 à 17:24, Chris Angelico <rosuav@gmail.com> a écrit :
On Thu, Apr 26, 2018 at 11:53 PM, Julian DeMille via Python-ideas <python-ideas@python.org> wrote:
That's the kind of thing I'm looking for. I've dealt with some library authors who were highly against importing the root allowing me to access submodules with hierarchy.
With a package, having automatic imports forces those submodules to be loaded eagerly (as soon as you import the package, you load up those modules). Lazily-loaded submodules can improve performance if you don't always need them.
+0 for an easier way to import multiple submodules at once. It's not something I've personally had a need for, but it's a sane and logical thing to do.
ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
27.04.18 02:12, Greg Ewing пише:
Chris Angelico wrote:
+0 for an easier way to import multiple submodules at once. It's not something I've personally had a need for, but it's a sane and logical thing to do.
Maybe:
import display, event, mixer in pygame
I read this as import display, event, mixer in pygame pygame.display = display pygame.event = event pygame.mixer = mixer del display, event, mixer in pygame
Serhiy Storchaka wrote:
27.04.18 02:12, Greg Ewing пише:
import display, event, mixer in pygame
I read this as
import display, event, mixer in pygame pygame.display = display pygame.event = event pygame.mixer = mixer del display, event, mixer in pygame
It's meant to be shorthand for import pygame.display import pygame.event import pygame.mixer -- Greg
26.04.18 16:51, Nick Coghlan пише:
Forcing submodule imports would be the main thing, as at the moment, you have to choose between repeating the base name multiple times (once per submodule) or losing the hierarchical namespace.
If the base name is short, there are no problems with repeating it. If it is long, it is better to get rid of this prefix than repeat it every time when you use submodules. In any case it takes pressing just a few keystrokes in modern editors for duplicating an import line for editing the last component.
So where:
from pkg import mod1, mod2, mod3
bind "mod1", "mod2", and "mod3" in the current namespace, you might instead write:
from pkg import .mod1, .mod2, .mod3
to only bind "pkg" locally, but still make sure "pkg.mod1", "pkg.mod2" and "pkg.mod3" all resolve at import time.
I think this special cases isn't special enough to introduce a special syntax.
On 27 April 2018 at 01:22, Serhiy Storchaka <storchaka@gmail.com> wrote:
I think this special cases isn't special enough to introduce a special syntax.
While I'm mostly inclined to agree, I do think it would be nice to have a clean spelling for "ensure this module is fully imported, but don't bind it locally". Right now, the most concise spelling I can think of for that would be to bind all the imported modules to the same throwaway variable, then delete that variable: import pkg from pkg import mod1 as __, mod2 as __, mod3 as __ del __ Allowing "as None" to mean "Don't bind this name at all" would give: import pkg from pkg import mod1 as None, mod2 as None, mod3 as None from . import views from .views import base as None It would be a bit odd though, since "None = anything" is normally a syntax error. Taking this idea in a completely different direction: what if we were to take advantage of PEP 451 __spec__ attributes to enhance modules to natively support implicit on-demand imports before they give up and raise AttributeError? (Essentially making all submodule imports implicitly lazy if you don't explicitly import them - you'd only be *required* to explicitly import top level modules, with everything under that being an implementation detail of that top level package) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On 27/04/2018 12:14, Nick Coghlan wrote:
On 27 April 2018 at 01:22, Serhiy Storchaka <storchaka@gmail.com> wrote:
I think this special cases isn't special enough to introduce a special syntax.
While I'm mostly inclined to agree, I do think it would be nice to have a clean spelling for "ensure this module is fully imported, but don't bind it locally".
How about a modifier for import such as: from module non_local import (a, b, c, d) or: from module import_named (a, b, c, d) I think that either gets the point across. -- Steve (Gadget) Barnes Any opinions in this message are my personal opinions and do not reflect those of my employer. --- This email has been checked for viruses by AVG. http://www.avg.com
On Fri, Apr 27, 2018 at 5:14 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
Taking this idea in a completely different direction: what if we were to take advantage of PEP 451 __spec__ attributes to enhance modules to natively support implicit on-demand imports before they give up and raise AttributeError? (Essentially making all submodule imports implicitly lazy if you don't explicitly import them - you'd only be *required* to explicitly import top level modules, with everything under that being an implementation detail of that top level package)
That might be interesting to explore. It smells like something related to the lazy import magic that Neil Shemenauer is working on. On the plus side, it means one less thing for programmers to do. On the minus side, I find the imports at the top of the file to be a nice catalog of external dependencies. Implicitly importing submodules would break that. The idea might be not as useful since the programmer would have to use the fully qualified name (relative to the "top-level" package). So why not just put that in the import statement? -eric
On 28 April 2018 at 02:18, Eric Snow <ericsnowcurrently@gmail.com> wrote:
On the plus side, it means one less thing for programmers to do. On the minus side, I find the imports at the top of the file to be a nice catalog of external dependencies. Implicitly importing submodules would break that.
The idea might be not as useful since the programmer would have to use the fully qualified name (relative to the "top-level" package). So why not just put that in the import statement?
I'm mainly thinking of it in terms of inadvertently breaking abstraction layers. Right now, implementation decisions of third-party package authors get exposed to end users, as the question of whether or not a submodule gets eagerly imported by the parent module, or explicitly configured as a lazy import, is exposed to end users: Parent package eagerly imports submodules: no explicit submodule import needed, just import the parent package Parent package explicitly sets up a lazy submodule import: no explicit submodule import needed, just import the parent package Parent package doesn't do either: possible AttributeError at time of use depending on whether or not you or someone else has previously run "import package.submodule" (or an equivalent) The current attribute error is cryptic (and not always raised if some other module has already done the import!), so trying the submodule import implicitly would also provide an opportunity to customise the way the failure is reported. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
Nick Coghlan wrote:
I find the imports at the top of the file to be a nice catalog of external dependencies.
Not only is it useful for human readers, it's also useful for packaging tools such as py2exe that need to know which modules are being used. I experimented once with auto-importing in PyGUI, but in the end I dropped it, partly because of this consideration. There were other problems with it as well. I don't recall all the details, but I think one issue is that any errors resulting from an import triggered by an attribute access get masked and turned into an AttributeError, making them very confusing to diagnose. Also, importing requires acquisition of the import lock, which could cause problems in a multithreaded environment if it happens at unpredictable times. For these reasons I'm inclined to regard auto-importing as an anti-pattern -- it seems like it should be a good idea, but it leads to more problems than it solves. -- Greg
The fact of explicit dependency noting is why I suggested something that explicitly defines multiple imports in one line On Sat, Apr 28, 2018 at 9:28 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Nick Coghlan wrote:
I find the imports at the top of the file to be a nice catalog of external dependencies.
Not only is it useful for human readers, it's also useful for packaging tools such as py2exe that need to know which modules are being used.
I experimented once with auto-importing in PyGUI, but in the end I dropped it, partly because of this consideration.
There were other problems with it as well. I don't recall all the details, but I think one issue is that any errors resulting from an import triggered by an attribute access get masked and turned into an AttributeError, making them very confusing to diagnose.
Also, importing requires acquisition of the import lock, which could cause problems in a multithreaded environment if it happens at unpredictable times.
For these reasons I'm inclined to regard auto-importing as an anti-pattern -- it seems like it should be a good idea, but it leads to more problems than it solves.
-- Greg _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- Thanks, Julian DeMille CEO, demilleTech, LLC This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.
On Thu, Apr 26, 2018 at 7:51 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On 26 April 2018 at 23:37, Paul Moore <p.f.moore@gmail.com> wrote:
What are the benefits of this over a simple "import <lib>"?
Forcing submodule imports would be the main thing, as at the moment, you have to choose between repeating the base name multiple times (once per submodule) or losing the hierarchical namespace.
So where:
from pkg import mod1, mod2, mod3
bind "mod1", "mod2", and "mod3" in the current namespace, you might instead write:
from pkg import .mod1, .mod2, .mod3
to only bind "pkg" locally, but still make sure "pkg.mod1", "pkg.mod2" and "pkg.mod3" all resolve at import time.
I'm not exactly sure what this thread is about. :) I'm pretty sure it's one of the following (in order of confidence): * explicit relative imports that bind to a fully qualified module name * combining absolute import statements, for submodules of the same package, into a single import statement Either way I don't think there's much point. For the relative import case it kind of defeats the point of relative imports. For the absolute import case there isn't much value added. I'll elaborate in the rest of this message. Combining Absolute Import Statements ============================== First, I'll get combining-absolute-import-statements case out of the way. Given the following example: # in cafe.spam from . import eggs, ham, bacon # or # from . import eggs # from . import ham # from . import bacon ... # use eggs # use ham # use bacon The equivalent absolute imports would be: import cafe.eggs import cafe.ham import cafe.bacon ... # use cafe.eggs # use cafe.ham # use cafe.bacon Under the proposed syntax it would be: # OP # This matches the layout of the existing absolute import # statement syntax. import cafe.{eggs, ham, bacon} # Nick # This matches the layout of the existing relative import # statement syntax (albeit without the dot). from cafe import .eggs, .ham, .bacon ... # use cafe.eggs # use cafe.ham # use cafe.bacon For one thing, having one import per line improves the programming experience, IMHO. (Then again, I'm a fan of "do at most one thing per line of code".) For readers one-import-per-line makes it easier to quickly identify the imported modules, and especially to match a module name in the code to its corresponding import statement. I do that often enough that I worry a combined syntax would obscure the names and lead to more effort, as a reader, to match them. Also, it's not like a module is going to import so many other modules (in the normal case) that one module per line is going to result in too many import lines at the top of the file. [1] Qualifying Relative Imports ===================== Second, I'll address the case of possibly fully qualifying relative imports. That seems reasonable enough at first glance. However, the point of relative imports is that you don't have to tie a module's code to the overall package hierarchy in your project (app/library). This helps you: * avoid mass refactoring when you choose to move a directory to somewhere else in the tree (or even to a different/new library) * make it clear to readers that the imported modules are part of the same library/app * make it clear to readers how the current module relates to the imported ones * (sometimes) keep your import statements shorter, benefiting you and readers alike; this is particularly relevant if you happen to have a deep directory structure (not a great situation, but sometimes appropriate) [2] Again, relative imports mean that your code does not become tied to your project's directory layout; and you only have to know the base name of the imported module and how it relates (in the directory structure) to the current module. Suppose we add a syntax like the following (equivalent to the above examples): # This matches the relative import syntax. from '.' import eggs, ham, bacon # Note the quotation marks around the dot. # This matches the absolute import syntax. import .eggs, .ham, .bacon ... # use cafe.eggs # use cafe.ham # use cafe.bacon In that case the code is tied to the directory layout, so why did we use relative imports in the first place? -eric [1] Just in case, I'll preemptively response to one possible concern: that each of the three import statements above is going to import the "pkg" module. However, at most the first one will actually import it. For the others the import machinery will short-circuit when it finds the module in sys.modules. [Nick is well aware of this, but I'd be surprised if the majority of Python programmers know this.] So the cost is not high enough to worry about it. [2] "Consenting adults" aside, explicit relative imports will typically be to sibling modules in a package. The more indirect the import, the more dependent the module is on a larger tree of packages which leads to more complexity for readers and more likelihood of breakage when packages move around.
participants (10)
-
Chris Angelico
-
Eric Snow
-
Greg Ewing
-
Julian DeMille
-
Nick Coghlan
-
Paul Moore
-
Pradyun Gedam
-
Robert Vanden Eynde
-
Serhiy Storchaka
-
Steve Barnes