Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

`~/.pythonrc' `from __future__ import'

0 views
Skip to first unread message

François Pinard

unread,
Jul 7, 2002, 6:12:15 PM7/7/02
to
Hello, people. Here is a strange problem with `from __future__ import',
maybe you can help me understand it. This is with Python 2.2.1.

Given `export PYTHONSTARTUP=/home/pinard/etc/pythonrc', and that `pythonrc'
file starting with:

---------------------------------------------------------------------->
from __future__ import division
print 3/4
----------------------------------------------------------------------<

then I interactively get:

---------------------------------------------------------------------->
18:01 0 pinard@titan:~ $ python
Python 2.2.1 (#1, Apr 29 2002, 14:27:21)
[GCC 2.95.3 20010315 (SuSE)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
0.75
>>> 3/4
0
>>> from __future__ import division
>>> 3/4
0.75
----------------------------------------------------------------------<

I wonder why I have to re-execute `from __future__ import divsion'
interactively before it works. How should I proceed to activate this
option once and for all for interactive applications?

--
François Pinard http://www.iro.umontreal.ca/~pinard


Tim Peters

unread,
Jul 7, 2002, 9:43:31 PM7/7/02
to
[François Pinard]

> Hello, people. Here is a strange problem with `from __future__ import',
> maybe you can help me understand it. This is with Python 2.2.1.
>
> Given `export PYTHONSTARTUP=/home/pinard/etc/pythonrc', and that
> `pythonrc'
> file starting with:
>
> ---------------------------------------------------------------------->
> from __future__ import division
> print 3/4
> ----------------------------------------------------------------------<
>
> then I interactively get:
>
> ---------------------------------------------------------------------->
> 18:01 0 pinard@titan:~ $ python
> Python 2.2.1 (#1, Apr 29 2002, 14:27:21)
> [GCC 2.95.3 20010315 (SuSE)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> 0.75
> >>> 3/4
> 0
> >>> from __future__ import division
> >>> 3/4
> 0.75
> ----------------------------------------------------------------------<
>
> I wonder why I have to re-execute `from __future__ import divsion'
> interactively before it works.

The PYTHONSTARTUP file acts as if executed via the execfile() function.
That implies it can leave behind visible bindings in the caller's globals,
and have other non-local side effects (such as importing other modules), but
like all exec and eval gimmicks, it executes in a code block distinct from
its caller's. It's a separately compiled unit, and a future statement's
useful effects are limited to the compilation unit in which it appears. In
effect, that means it only "works" for the code in the startup file itself.

Note that Python has no equivalent in this respect to what some shells call
a "source" command.

> How should I proceed to activate this option once and for all for
> interactive applications?

You can write an alias to start interactive sessions by passing -Qnew to
Python. Then future division will be in effect globally (note: that means
globally, including across all imported library modules, and some non-core
library modules may not yet work correctly when future division is in
effect; so -Qnew can't be recommended for general use, but is fine if
you're, umm, motivated <wink>).


François Pinard

unread,
Jul 8, 2002, 8:05:39 AM7/8/02
to
[Tim Peters]

> > How should I proceed to activate this [future division] ]option once


> > and for all for interactive applications?

> You can write an alias to start interactive sessions by passing -Qnew to
> Python.

I've heard about this undocumented feature indeed, and hoped to go without
resorting to it. Moreover, this option only works for division, it does
not apparently activate generators, for instance. I would rather have
all future features available all the time when I write interactively,
yet I guess why some people would prefer not.

> The PYTHONSTARTUP file acts as if executed via the execfile() function.
> That implies it can leave behind visible bindings in the caller's
> globals, and have other non-local side effects (such as importing other
> modules), but like all exec and eval gimmicks, it executes in a code
> block distinct from its caller's. It's a separately compiled unit,
> and a future statement's useful effects are limited to the compilation
> unit in which it appears. In effect, that means it only "works" for
> the code in the startup file itself.

I understand and, Tim, I thank you for your patient explanations, However,
it wonder if this is all fully right. The actual documentation and the
PEP say that one could `import __future__' explicitly, so to check at
run time what features are currently available in the running Python.
Besides its compile-time effect, `from __future__ import division' (say)
dynamically defines `division' at run-time in the global space, at least
when done from the startup file, but this is no strong clue about if the
feature has been activated or not (at least when the Python version lies
between the introduction version and, excluded, the mandatory version).

Would it mean that one has no other choice than "benchmark" the feature at
run-time, the ugly way, to know whether it is active or not? The current
intent is to let an `from __future__ import FEATURE' generate an error if
the FEATURE is wanted in a module, but not available in the current Python.

Suppose, for example, that I write a module in which some function makes
good use of some future feature (it could be the `yield, statement),
but I want to provide an alternate implementation of that function which
is less interesting (because it gets much complex and slower) in case the
feature is not available. Since I cannot except out of the `from __future__
import' statement, for reasons I understand, I do not see how I take good
advantage of available future features, in a program meant to be portable
between versions. Maybe the future statement is rougher than I expected?

Michael Hudson

unread,
Jul 8, 2002, 9:21:40 AM7/8/02
to
pin...@iro.umontreal.ca (François Pinard) writes:

> Suppose, for example, that I write a module in which some function makes
> good use of some future feature (it could be the `yield, statement),
> but I want to provide an alternate implementation of that function which
> is less interesting (because it gets much complex and slower) in case the
> feature is not available. Since I cannot except out of the `from __future__
> import' statement, for reasons I understand, I do not see how I take good
> advantage of available future features, in a program meant to be portable
> between versions. Maybe the future statement is rougher than I expected?

I think you more-or-less have to have separate modules for the
differently versioned functionality, eg.

try:
from two_point_two_using_module import func
except SyntaxError: # is that what bogus future statements should
# really raise? too late now, I guess
from two_point_one_using_module import func

...

Writing code that uses 2.2 features where possible but still runs on
2.1 is a pain, but I'm not sure how it could have been done better,
really.

Cheers,
M.

--
I have a feeling that any simple problem can be made arbitrarily
difficult by imposing a suitably heavy administrative process
around the development. -- Joe Armstrong, comp.lang.functional

François Pinard

unread,
Jul 8, 2002, 11:36:42 AM7/8/02
to
[Michael Hudson]

> try:
> from two_point_two_using_module import func
> except SyntaxError: # is that what bogus future statements should
> # really raise? too late now, I guess
> from two_point_one_using_module import func

> Writing code that uses 2.2 features where possible but still runs on


> 2.1 is a pain, but I'm not sure how it could have been done better, really.

I agree with you, thanks for the hints. Your approach is workable, at
least for packages big enough to warrant many modules. It might also
mean that for really simple packages, such portability is not affordable,
so better plainly write for the oldest Python one wants to support.

Tim Peters

unread,
Jul 8, 2002, 2:34:18 PM7/8/02
to
[François Pinard]

>>> How should I proceed to activate this [future division] ]option once
>>> and for all for interactive applications?

[Tim]


>> You can write an alias to start interactive sessions by passing -Qnew to
>> Python.

[François]


> I've heard about this undocumented feature indeed, and hoped to go without
> resorting to it.

All the -Q options are documented in the division PEP:

http://www.python.org/peps/pep-0238.html

> Moreover, this option only works for division, it does not apparently
> activate generators, for instance.

Yes, -Q is specific to division, as will become clear if you read the PEP
238 "Command Line Option" section.

> I would rather have all future features available all the time when I
> write interactively, yet I guess why some people would prefer not.

There's no way to do that, short of fiddling Python's source code.

> ...


> However, it wonder if this is all fully right. The actual documentation
> and the PEP say that one could `import __future__' explicitly, so to
> check at run time what features are currently available in the running
> Python.

You could, although I advise against it (see below). For example,

"""
import sys

try:
import __future__
div = __future__.division

except ImportError:
print "This version of Python predates __future__ statements."

except AttributeError:
print "This version of Python never heard of future-division."

else:
opt = div.getOptionalRelease()
mand = div.getMandatoryRelease()
if mand is None:
print "It was decided to drop future division."
elif sys.version_info >= mand:
print "future-division is enabled by default."
elif sys.version_info >= opt:
print "future-division is available if you explicitly ask for it."
else:
print "future-division isn't yet available."
"""

prints the truth about future-division under any version of Python that ever
was or ever will be <wink> released.

> Besides its compile-time effect, `from __future__ import division' (say)
> dynamically defines `division' at run-time in the global space, at least
> when done from the startup file,

Yes, its runtime effect is the same as

from math import cos
or
from difflib import SequenceMatcher

or any other "from ... import ..." statement.

> but this is no strong clue about if the feature has been activated or
> not (at least when the Python version lies between the introduction
> version and, excluded, the mandatory version).

That "from __future__ import division" doesn't raise an exception means
you're in one of the four states covered by the "else:" clause above. The
code there shows how to distinguish among those, but again I don't recommend
trying to do so. The possibility for this kind of introspection is for
heavy-duty site-management tools (should anyone wish to implement such
things).

> Would it mean that one has no other choice than "benchmark" the feature at
> run-time, the ugly way, to know whether it is active or not? The current
> intent is to let an `from __future__ import FEATURE' generate an error if
> the FEATURE is wanted in a module, but not available in the current
> Python.
>

> Suppose, for example, that I write a module in which some function makes
> good use of some future feature (it could be the `yield, statement),
> but I want to provide an alternate implementation of that function which
> is less interesting (because it gets much complex and slower) in case the
> feature is not available. Since I cannot except out of the `from
> __future__
> import' statement, for reasons I understand, I do not see how I take good
> advantage of available future features, in a program meant to be portable
> between versions. Maybe the future statement is rougher than I expected?

It's less ambitious than you may want it to be. It was emphatically not the
intent of future-statements to create multiple "pick and choose" dialects of
Python. Its only design goal was to provide a transition period between
flat-out incompatible semantics, where during the transition period you:

1. Continue to get the old semantics, but also get warnings about
code that's going to break when the semantics change.

and

2. You can explicitly request the new semantics on a module-by-module
basis, to aid in reworking legacy code incrementally.

#2 is intended for people who want an easy way to turn new semantics on and
off while redoing their code, a bit at a time, to work either way --
provided they care about that.

For everyone else, a future-feature is a planned experimental feature that
may even get dropped (hence the possibility for .getMandatoryRelease() to
return None). Portable distributed code should never contain a future
statement! It wasn't designed for that, and, as you've discovered, trying
to use it for that sucks. It's not for portability: it's a temporary aid
to ease the transition between incompatible semantics.

Note that, e.g., the only reason generators got put under the __future__
machinery is that they make "yield" a new keyword. That's "flat-out
incompatible semantics", and the only purpose of the future machinery here
is to give people a release cycle in which to rename their existing "yield"
identifiers (provided they have any -- I haven't yet found any code that
does, although I'm sure some exists somewhere).

the-point-of-__future__-is-mostly-to-ease-living-in-the-past-ly y'rs - tim


François Pinard

unread,
Jul 8, 2002, 3:14:19 PM7/8/02
to
[Tim Peters]

> All the -Q options are documented in the division PEP:
> http://www.python.org/peps/pep-0238.html

Thanks for the reference, I'll take a look. One one hand, a future-related
option is not going to be extensively documented in the reference manual.
On the other hand, thinking about it, it could probably be documented
at least in the Python `man' page, since the option exists as of now.
Probably not worth the fuss? :-)

> > However, it wonder if this is all fully right. [...] to check at run


> > time what features are currently available in the running Python.

> You could, although [...] It was emphatically not the intent of


> future-statements to create multiple "pick and choose" dialects of Python.
> Its only design goal was to provide a transition period between flat-out

> incompatible semantics [...]

Let me thank you, Tim, for this comprehensive and enlightening answer!
I'm carefully saving it for later meditation. :-)

Thomas Bellman

unread,
Jul 8, 2002, 8:56:30 PM7/8/02
to
Tim Peters <tim...@comcast.net> wrote:

> [François Pinard]

>> Moreover, this option only works for division, it does not apparently
>> activate generators, for instance.

> Yes, -Q is specific to division, as will become clear if you read the PEP
> 238 "Command Line Option" section.

>> I would rather have all future features available all the time when I
>> write interactively, yet I guess why some people would prefer not.

> There's no way to do that, short of fiddling Python's source code.

Well... At least under Unix there is a way... Put this code in
your ~/.pythonrc:

import fcntl, termios, __future__

dels = "fcntl, termios, __future__, dels, feature, c"
for feature in __future__.all_feature_names:
dels += ", " + feature
for c in "from __future__ import " + feature + "\n":
fcntl.ioctl(1, termios.TIOCSTI, c)
for c in "del "+dels+"\n":
fcntl.ioctl(1, termios.TIOCSTI, c)

(Unfortunately, __future__.all_feature_names isn't in Python 2.1,
so if you need your .pythonrc file to be portable to 2.1 you will
have to filter out the relevant names from dir(__future__). I
leave that as an exercise for the readers.)

Now, I didn't say it was *elegant*, but it seems to work on at
least a couple of Unix dialects.


--
Thomas Bellman, Lysator Computer Club, Linköping University, Sweden
"The one who says it cannot be done should ! bellman @ lysator.liu.se
never interrupt the one who is doing it." ! Make Love -- Nicht Wahr!

François Pinard

unread,
Jul 8, 2002, 10:34:07 PM7/8/02
to
[Thomas Bellman]

> Well... At least under Unix there is a way... Put this code in

> your ~/.pythonrc: [...]

Wow! It even works!! Thanks a lot for the tip! :-)

Michael Hudson

unread,
Jul 9, 2002, 9:53:16 AM7/9/02
to
bel...@lysator.liu.se (Thomas Bellman) writes:

> Tim Peters <tim...@comcast.net> wrote:
>
> > [François Pinard]
>

> >> I would rather have all future features available all the time when I
> >> write interactively, yet I guess why some people would prefer not.
>
> > There's no way to do that, short of fiddling Python's source code.
>
> Well... At least under Unix there is a way... Put this code in
> your ~/.pythonrc:

You're a bad man! Cool hack, though.

Cheers,
M.

--
Presumably pronging in the wrong place zogs it.
-- Aldabra Stoddart, ucam.chat

0 new messages