[Python-ideas] Idea: Importing from arbitrary filenames

Wes Turner wes.turner at gmail.com
Sat Apr 14 01:12:58 EDT 2018


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 <kenlhilton at 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?
>
> ​Regards
> ,
> Ken
> ​ Hilton​
> ;
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180414/d252f126/attachment.html>


More information about the Python-ideas mailing list