I'm fairly certain similar changes have been discussed in the past. Someone
else can probably find / link / rehash the reasons why imports deliberately
use dot notation instead of path?
I can think of a few:
1) Portability. dotted imports looked up from sys.path are platform-portable
2) Flexibility. importlib Loaders (3.1+) are abstract; they only know what
to do with dotted paths. They can import from the filesystem, zip files,
... git repos,
sys.path (`python -m site`) can be configured with:
- modules.py and dirs/__init__.py in site-packages/
- .pth files in site-packages/
- idempotent sys.path config at the top of a .py source file
- sys.USER_SITE in sys.path
Is there a good write-up of how, where, and in what order sys.path is
configured, by default, in Python?
TLDR dotted names are preferable for sharing code with people who don't
have the same paths, os.pathsep, or os.platform_info. (Stevedore and
Jupyter Notebook take different approaches to handling plugins, if that's
your use case?)
Though I could just be arguing for the status quo; there are probably good
reasons to consider changing EVERYTHING
On Friday, April 13, 2018, Ken Hilton <kenlhil...@gmail.com> wrote:
> Hi all,
> First of all, please excuse me if I'm presenting this idea in the wrong
> way or at the wrong time - I'm new to this mailing list and haven't seen
> anyone propose a new idea on it yet, so I don't know the customs.
> I have an idea for importing files with arbitrary names. Currently, the
> "official" way to import arbitrary files is to use the "imp" module, as
> shown by this answer: https://stackoverflow.com/a/3137914/6605349
> However, this method takes two function calls and is not as (aesthetically
> pleasing? is that the word?) as a simple "import" statement.
> Therefore, my idea is to allow the "import" statement to accept one of
> three targets.
> First, the normal "import":
> import antigravity
> which simply imports from sys.path.
> Second, importing with a string literal specifying the path to a file:
> import '/home/pi/anti-gravity.py' *as antigravity*
> Note the "as antigravity" in this statement - this is to avoid ambiguities
> when choosing the global name to bind to. Should "import
> '/home/pi/anti-gravity.py'" import to the name "/home/pi/anti-gravity.py",
> "anti-gravity.py", "anti-gravity", or "anti_gravity"? None of those are
> really ideal. Therefore, when the import target is a string literal, the
> statement must include "as NAME".
> Third, importing with an expression providing a value castable to a
> string, specifying the path to a file:
> def file_in_home(filename):
> return '/home/pi/' + filename
> import *$*file_in_home('anti-gravity.py') *as antigravity*
> Once again, for the same reasons, import statements like this must include
> "as NAME" to avoid ambiguities. Notice that the expression is preceded by a
> dollar sign ($) to indicate that what follows is an expression rather than
> a name - imagine a scenario like this:
> antigravity_file = '/home/pi/anti-gravity.py'
> import antigravity_file as antigravity
> Should it look for a sys.path module with the name "antigravity_file" or
> should it use the value of the variable "antigravity_file"? Looking for the
> sys.path module first before trying a variable's value would waste
> processing time and potentially be unexpected behavior. Trying a variable's
> value first before looking for a sys.path module would be even less
> expected behavior. Therefore, a dollar sign must come before expression
> imports to indicate that the import target is an expression.
> Side note: the dollar sign was chosen because it mimics other languages'
> conventions of preceding variable names with dollar signs, but any
> arbitrary character not present at the start of an expression would work.
> One more thing about expression imports: if the final returned value of
> the expression is not a string, I believe the statement should raise a
> TypeError (the same way that __repr__ or __str__ raise TypeError if they
> return a non-string). Why? If the statement attempted to cast the return
> value to a string, and the return value's __str__ method raised an error,
> then should the statement allow the error to pass through, or should it
> attempt to use a parent class's __str__ method? Allowing the error to pass
> through would almost certainly be unexpected behavior; attempting to use a
> parent class's __str__ method would take more time and more processing
> power (though it would eventually reach "object"'s __str__ method and
> succeed). Therefore, non-string expression values should raise TypeError.
> What are your thoughts?
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/