[Python-Dev] Breaking undocumented API
Eric Smith
eric at trueblade.com
Thu Nov 11 21:44:23 CET 2010
On 11/10/2010 11:58 AM, Tres Seaver wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 11/09/2010 11:12 PM, Stephen J. Turnbull wrote:
>> Nick Coghlan writes:
>>
>> > > Module writers who compound the error by expecting to be imported
>> > > this way, thereby bogarting the global namespace for their own
>> > > purposes, should be fish-slapped. ;)
>> >
>> > Be prepared to fish-slap all of python-dev then - we use precisely
>> > this technique to support optional acceleration modules. The pure
>> > Python versions of pairs like profile/_profile and heapq/_heapq
>> > include a try/except block at the end that does the equivalent of:
>> >
>> > try:
>> > from _accelerated import * # Allow accelerated overrides
>> > except ImportError:
>> > pass # Use pure Python versions
>>
>> But these identifiers will appear at the module level, not global, no?
>> Otherwise this technique couldn't be used. I don't really understand
>> what Tres is talking about when he writes "modules that expect to be
>> imported this way". The *imported* module shouldn't care, no? This
>> is an issue for the *importing* code to deal with.
>
> Right -- "private" star imports aren't the issue for me, because the
> same user who creates them is responsible for the other end fo the
> stick. I was ranting about library authors who document star imports as
> the expected usage pattern for their external users.
>
> Note that I still wouldn't use star imports in the "private
> acceleration" case myself. I would prefer a pattern like:
>
> - ----------------------- $< -----------------------------
> # spam.py
>
> # Pure python API implementation
> def foo(spat, blarg):
> ...
>
> def bar(qux):
> ...
>
> # Replace with accelearated C implemenataion
> try:
> import _spam
> except ImportError:
> pass # accelerated version not available
> else:
> foo = _spam.foo
> bar = _spam.bar
> - ----------------------- $< -----------------------------
>
> This explicit name remapping catches unintentional erros (e.g., _spam
> renames a method) better than the star import.
But then you're saying that all implementations of _spam have to support
the same API. What if CPython's _spam has foo, bar, and baz, but
Jython's only has foo and bar, and IronPython's only has baz? Without
getting into special casing or lots of try/catch blocks on individual
names, I think import * is the best way to go.
Eric.
More information about the Python-Dev
mailing list