On Sun, Jan 19, 2020 at 08:09:32PM -0300, Soni L. wrote:
We have importlib. We have importlib.resources. We can import modules. We cannot (yet) import resources using the same-ish module import machinery.
Actually we can, using importlib.resources, which you already mentioned. The machinery is right there, although the documentation lacks a good tutorial or How To. Nevertheless, I got it to work correctly the first time after less than a minute's reading of the docs: * create a package in the PYTHONPATH spam/ +-- __init__.py * add a text file "config" under the spam directory * run: import importlib.resources import spam rsrc = importlib.resources.read_text(spam, "config") and it Just Works. What we can't (easily) do is import resources using the import *syntax*. I am lead to believe that there is such as thing as "import hooks" that let you customize how and what gets imported. I have no idea how these hooks work, perhaps there's a good How To or guide somewhere? But as I understand it, you could right a hook which allows you to use the import syntax to load any thing you want from anywhere you want, so long as it fits into the existing import syntax.
from foo.bar import resources "foo.txt" as foo, "bar.txt" as bar
The downsides of this proposal include: (1) It requires a new keyword, one which I'm sure will clash with about a thousand bazillion modules that already use "resources" as a variable. (2) It requires a change to the syntax of import statements to allow quoted file names, or else it requires you to name your data files with names which are legal identifiers. E.g. "foo" rather than "foo.txt". I don't think this functionality is important enough or common enough to warrant not one but two new pieces of syntax, not when it is so easy to get the same functionality using the functional syntax rsrc = importlib.resources.read_text(spam, "config") But perhaps you can start with an import hook that lets you write: import spam.config as rsrc and leave the functional syntax for file names which aren't valid identifiers.
or maybe:
foo = f"{from foo.bar import 'foo.txt'}"
An f-string is a disguised eval expression that returns a string. Using the same f-string syntax as a disguised import statement is a great example of the "Golden Hammer" anti-pattern applied to language design. "F-strings are cool, so we should make completely unrelated things like loading resources look like an f-string!". https://en.wikipedia.org/wiki/Law_of_the_instrument This likewise has a disadvantage that it requires new syntax. F-strings are expressions and they requires all the evaluated terms to be expressions, not statements: py> f'{import math}' File "<fstring>", line 1 (import math) ^ SyntaxError: invalid syntax so your proposal would require f-strings to: * accept import and from...import statements as a special case; * rather than eval these terms, exec them, while still eval'ing everything else; * but using a special, implicit, version of import which calls importlib.resources.read_text rather than the standard import; * leading to confusion when people try things like f'{from math import pi}' and get a surprising TypeError that math is not a package. -- Steven