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
# $HOME/\this\/__init__.py
sys.path.append(
os.path.expanduser(
os.path.join('~', 'this',)))
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,
https://docs.python.org/3/library/importlib.html
https://docs.python.org/3/library/importlib.html#importlib.abc.SourceLoader
https://pypi.org/search/?q=importlib
https://docs.python.org/3/library/imp.html#imp.find_module
https://docs.python.org/3/library/imp.html#imp.load_module
sys.path (`python -m site`) can be configured with:
- $PYTHONSTARTUP='~/.pythonrc.py'
- 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
- ~/.local/lib/python*X.Y*/site-packages
- ~/Library/Python/*X.Y*/lib/python/site-packages
- *%APPDATA%*\Python\Python*XY*\site-packages
- https://docs.python.org/3/library/site.html
- https://docs.python.org/3/using/cmdline.html#envvar-PYTHONSTARTUP
- https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUSERBASE
- https://docs.python.org/3/library/site.html#site.USER_SITE
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
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?
Regards , Ken Hilton ;