Just thinking about how nice it is in Rust that you can write
to reference a function in another module without a use statement to bring it into this namespace.
Edit: I described below why this is nice: you can use it in the middle of coding something without either stopping to add an import or adding a mental to-do to do so.
The use statement would look like
which is similar in behaviour to Python’s import.
The :: syntax isn’t available in Python because name[start::step] already has a meaning.
What about import x.y as an expression?
for x in (import itertools).chain(xs, ys, vz):
It is almost always itertools where I want this, or contextlib or collections or some other helper.
As a bonus, this would promote the use of lazy imports which sometimes make programs start faster (I used to avoid these they would ImportError later than they could; these days I’m sad about the cost of imports that are often not used).
As a dunder name, I believe that __import__ is now considered to be
for use by the interpreter. I think that that recommended way to refer
to an import using an expression is to use importlib.import_module.
Unless you are playing code golf, or writing obfuscated Python, or
trying to break out of a sandbox inside eval() or exec(), I think using __import__ is a bit wiffy.
I agree with Paul that putting the imports at the top of the module is
better, oh, 98% of the time. The other 2% of the time, it might be
useful to look at better ways to do lazy imports.
I’m not convinced that a import expression is the right way to do it,
but I’m keeping an open mind.
Thinking out loud… what if we had a module proxy object that didn’t
actually do the nuts and bolts of loading the module until the first
time you actually used it (by attribute access)?
import itertools lazily
assert isinstance(itertools, LazyModule)
# much later
itertools.chain # first attribute access loads the module
assert isinstance(itertools, ModuleType)
(import x).y is quite verbose which is okay if it’s only used sparingly but can add a lot of noise if it isn’t. If you agree that best practices are best enforced by the language’s grammar, this probably isn’t the best way to approach inline imports. The problem you are describing I’d think is better solved by an IDE. Granted, IDEs tend to place imports at the top and you’ll have to go out of your way to remove them, which might happen often when prototyping (and care about unused imports), but c’est la vie.
I’m recently furious about an IDE (VS Code) having quietly inserted the line
from os import initgroups
into a module that I was working on. This was in a game jam (PyWeek) and it meant my entry crashed on Windows. For all I know this cost me the competition victory. I didn’t even type initgroups and honestly it isn’t even a function I knew about.
This is not something better solved by IDEs. IDEs can *@%! right off.
(I didn’t storm off after this experience to come here and post this idea, and I am not consciously aware that my fury about this experience directly influenced this proposal. You just brought it up and now i’m angry about it again.)
I do think it would be fine if IDEs (grr) or code formatters like isort (yay) hoisted the import expression I actually intentionally typed out to the top of the file. But for that to be a thing, first import expressions need to be a thing.
Leaving aside whether this is something we may have or not, you can have this
by creating a namespace object which takes care of the import dynamically
whenever it gets asked to return an attribute it doesn’t yet know.
Nice hack! You would have to return a pretty muddy proxy object in order to support
It would have to try attribute access, fall back to importing and if the import fails with ModuleNotFoundError, re-raise the AttributeError? So it can’t clearly distinguish import errors and attribute errors. I guess it could raise a MultiException, not sure whether that has appropriate semantics.
But, it feels too magical for my taste. If someone wrote this as a PyPI package I’d think it was cute but wouldn’t use it.
This is something that happens to me quite a lot, but in a Python interpreter console, and usually I’ll recognise the need for an import a few more tab-stops in. Importing anything currently would mean I have to cancel the entire code-block, import, then do everything again.
I know this is solved currently by Jupyter, but that’s very slow to start up when I need to do a quick calculation. An inline import would solve my problem here
Why is your tone so aggressive? I wasn’t suggesting Python learns inline importing so my problem is resolved, rather I’m giving an argument for the idea. If I wanted an existing solution, I could just use __import__ (with no concern about compatibility, as I’m using it in an interactive session), or as I say, use Jupyter.
The more I think about it, the more convinced I am that lady imports are the better solution in modules here over inline imports. Ignoring the performance impact of local imports, having them declared at the top of a follow has allowed me to easily see a module’s dependencies
Your IDE or editor might be able to help here. The Python plugin for VSCode suggests modules that aren’t imported and will automatically add them to your imports if you accept the suggestion. Alternatively I believe there are plugins that let you select a word and add it to your imports with a keyboard shortcut if you find the suggestions too annoying.
Even though I disagree with ideas about adding this syntax into python, I agree that simple scripting should be fun and we should have nice syntax to play with.
So here you go:
Has it been rigorously tested? Not at all! Should you use it in production? Certainly not.
But nevertheless, it is fun. You can use it in place of a python alias. I.e. impexpr my_file.py will run that file with import expressions. Additionally, all files that it imports will also support import expressions. impexpr will open an interactive repl that supports import expressions (though this repl is a lot weaker than Python’s repl but I’m sure that if ideas get popular enough, we’ll fix that)
It uses an amazing library ideas created specifically for use-cases such as yours. I think @aroberge will also be interested in this discussion.