[Python-ideas] Making it easy to prepare for PEP479

Steven D'Aprano steve at pearwood.info
Mon May 18 18:18:27 CEST 2015


On Tue, May 19, 2015 at 12:13:21AM +1000, Chris Angelico wrote:
> On Mon, May 18, 2015 at 11:32 PM, Joao S. O. Bueno
> <jsbueno at python.org.br> wrote:
> > Indeed - importing as NOP would surely be broken -
> >
> > The nice fix would be to be able to do
> > from __future__ import jaberwock
> >
> > and have a plain "ImportError" that could be catched.
> 
> Indeed. Though I'm not sure what a correctly-spelled "from __future__
> import jabberwock" would do; exceptions already "burble" up the call
> stack until they meet "the clause that catch[es]" them. :)

You cannot catch errors in "from __future__ import" lines, because they 
are compile-time errors, not runtime errors. Any __future__ lines must 
be the first lines of executable code in the module. Only comments, 
blank lines, the module docstring, and other __future__ lines can 
preceed them, so this cannot work:

try:
    from __future__ import feature
except:
    pass


for the same reason that this cannot work:

try:
    thing = }{
except SyntaxError:
    thing = {}


It is best to think of the __future__ imports as directives to the 
compiler. They tell the compiler to produce different code, change 
syntax, or similar. Except in the interactive interpreter, you cannot 
change the compiler settings part way through compiling the module.

There is a real __future__ module, but it exists only for introspection 
purposes.


[...]
> The way to make this work would be two-fold. Firstly, an incorrect
> __future__ directive would have to no longer be a SyntaxError; and
> secondly, __future__ directives would have to be permitted after a try
> statement (currently, they're not allowed to follow anything, so the
> 'try' would have to be special-cased to be allowed in). 

It's not enough to merely change the wording of the error from 
SyntaxError to something else. You have to change when it occurs: it can 
no longer be raised at compile time, but has to happen at run time. That 
means that __future__ imports have to have compile to something which 
runs at run time, instead of just being a directive to the compiler.

As for the changes necessary to the compiler, I have no idea how 
extensive they would be, but my guess is "extremely".

Also, consider that once you are allowing __future__ directives to occur 
after a try statement, expect there to be a lot more pressure to allow 
it after any arbitrary code. After all, I might want to write:

if sys.version != '3.7' and read_config('config.ini')['allow_jabberwocky']:
    from __future__ import jabberwocky

so you're opening the doors to a LOT more complexity.

Which, as far as I am concerned, is a good thing, because it makes the 
chances of this actually happening to be somewhere between Buckley's and 
none *wink*



-- 
Steve


More information about the Python-ideas mailing list