Closed 1d332e54-3b86-44a9-8fc6-e0c6e60d2a36 closed 23 years ago
This is a reference implementation for the PEP proposal. Here, the patch has existed before the PEP, therefore the PEP refers to the patch... I need to create the patch before I submit the PEP :)))
Frederic Giacometti
-----------------------
PEP XXX: ImportNotFoundError Exception
fred@arakne.com (Frederic Giacometti)
Abstract
The object of this proposal is the definition of a specific ImportNotFoundError error, along with its association to a new import exception trapping mechanism that will enable the extension of the import mechanism to generic global/static objects.
Part 1: The ImportNotFoundError exception.
In the present code, the ImportError string exception is used for all import failures; this does not permit us to catch efficiently import failures caused specifically by a 'component not found' situation.
To fix this, we introduce a new exception, that we call ImportNotFoundError. This exception is designed for use in the very specific situation where an import string cannot be found by the import mechanism (as opposed to 'found' but 'failed to open', failed to load', 'failed to initialize'...).
ImportNotFoundError instance raised within execution of an import statement will have two attributes as follows:
A formal Python definition of ImportErrorNotFound could be:
class ImportNotFoundError( ImportError):
def __init__( self, parent, name):
assert( hasattr( parent, '__name__'))
assert( sys.modules.has_key( parent.__name__))
assert( sys.modules[ parent.__name__] is parent)
assert( not hasattr( parent, name))
ImportError.__init__( self, parent, name)
self.parent = parent
self.name = name
2) Alternative import customization hook in the module global scope (altimp)
2.a: Why in the module global scope? (or: Why not overwrite builtins.__import__?)
Use of builtins.__import is not a preferred integration practice: Only one __import value can be defined; and if you're integrating two components with each its own __import__ version, you'll be stuck...
Furthermore, if one insists on overwriting __import, one can still do it. Meanwhile, if an application requires overwriting __import, and one does not want to, one is stuck again...
Since we want to keep options open, we're proposing to enhance the import procedure defining a trapping mechanism based on the presence of a globals()[ '__altimp__'] object, which is called if present upon trigger of an ImportNotFoundError within an import statement.
In doing so, those who don't want (rightfully) to be bothered won't be, unless they define __altimp in their module global scope, and a module's usage of a certain implementation of __altimp won't bother other modules, at all.
2.b Definition
If present, globals()[ '__altimp__'] will refer to a callable object specified as follows:
def importextended( failedparent, failedname, name,
globs=None, locs=None, fromlist=None):
failedparent: 'parent' attribute from the ImportnotFoundError exception
failedname: 'name' attribute from the ImportnotFoundError exception
(name, globs, locs, fromlist): same arguments as in __import__()
return: same as in __import__() [object for insertion in sys.modules...]
Effect on existing code
There should be no effect on existing code, other than when code like exc.__class__ == ImportError has been meant for isinstance( exc, ImportError)
(hopeless anyway? :(()
Applications:
Given that importext.py contains:
__all__ = ('importextended')
import sys
def importextended( failedparent, failedname, name,
globs=None, locs=None, fromlist=None):
curmod = failedparent
remainder = name[ len( curmod.__name__) + 1:].split( '.')
while remainder:
curname = remainder.pop( 0)
curmod = getattr( curmod, curname)
sys.modules[ curmod.__name__] = curmod
return curmod
A JPE file may contain:
# import Java's javax.swing package in global scope
from importext import importextended as __altimport__
from java import Jstring
from java.system.javax import swing
frame = swing.JFrame( Jstring( 'HelloWorldSwing'))
label = swing.JLabel( Jstring( 'Hello World'))
frame.getContentPane().add(label)
frame.setDefaultCloseOperation( swing.JFrame.EXIT_ON_CLOSE)
frame.pack()
frame.setVisible( 1)
A Metadynamic Python file can contain:
# User is a Metaphase persistant class
from importext import importextended as __altimport__
from metadyn.mclass import User
users = mclass.User.QueryDbItem( some_query)
...
Based on this feature, applications can easily be programmed on the client side for any client/server situation, including pulling Python modules from remote repository...
Reference Implementation:
A sample implementation of ImportErrorNotFoundError in the current import mechanism, with the __altimp__ hook is provided in patch href:attached_file.
Logged In: YES user_id=21627
There is in general no need to put the PEP into the SF comment. Just send it to the PEP editor, who should assign a PEP number and commit it into CVS in a timely manner.
I have a number of comments on this PEP, but I'll send them directly to you once the PEP is on python.sf.net/peps.
Logged In: YES user_id=6380
Rejected. The "PEP" doesn't provide a motivation for the ImportNotFound error, and I don't see a reason why this particular condition should be excepted.
The __altimp__ idea is a nice one, but the elaboration here is incomprehensible. I suggest that you submit this idea as a separate patch.
Logged In: YES user_id=93657
The 'motivation' is at the beginning of the first section of the PEP. I'm pasting it below:
Part 1: The ImportNotFoundError exception.
In the present code, the ImportError
string exception is used for all import failures; this does not permit us to catch efficiently import failures caused specifically by a 'component not found' situation.
To fix this, we introduce a new
exception, that we call ImportNotFoundError. This exception is designed for use in the very specific situation where an import string cannot be found by the import mechanism (as opposed to 'found' but 'failed to open', failed to load', 'failed to initialize'...).
Logged In: YES user_id=6380
What's missing is why an application would need to catch this kind of import failures. I have a limited imagination, and I can't come up with a scenario that would require this. That's what I meant by "motivation".
Logged In: YES user_id=93657
There are two application scenarios for __altimp, and the __altimp implementation requires ImportNotFoundError.
The introduction of ImportNotFoundError is the only way I could find to implement efficiently __altimp__ .
I'm giving below an similar implementation in Python that overrides __import__ (with the inconvenient that this affects all import statements). A possible importextended function is defined in the [sample] 'Application' section of the PEP :
------------
pyimport = __import__
def altimport( name, globs=None, locs=None, fromlist=None):
try:
return pyimport( globs, locs, fromlist)
except ImportNotFoundError, iexc:
return importextended( iexc.parent, iexc.name, name,
globs, locs, fromlist)
sys.__buildins__.__import__ = altimport
Let's make clear that in this case I only want to catch the ImportError's corresponding to something whose import fails because it is not on the filesystem (not on PYTHONPATH....), and that I do not want to catch any other case of ImportError that could be raised. Thus, a subclass of ImportError is needed: ImportNotFoundError.
FG
Logged In: YES user_id=6380
The existing import hooks have ways to do this without catching the exception.
Logged In: YES user_id=93657
How? You could at least give a pointer, a word, something!
FG
Logged In: YES user_id=21627
One option is to subclass ihooks.ModuleLoader and redefine find_module and find_module_in_dir, always calling the base class method and taking action only when those return None.
It seems that ImportNotFound is not precisely specified. Suppose I have
#foo.py
import bar
print "Done"
and suppose bar is not available. Now, the application performs
import foo
Should it get an ImportNotFoundError? Importing bar probably raised one, but foo.py is present, so importing foo should raise a plain ImportError.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields: ```python assignee = None closed_at =
created_at =
labels = ['interpreter-core']
title = 'Implemenation of ImportNotFoundError PEP'
updated_at =
user = 'https://bugs.python.org/giacometti'
```
bugs.python.org fields:
```python
activity =
actor = 'loewis'
assignee = 'none'
closed = True
closed_date = None
closer = None
components = ['Interpreter Core']
creation =
creator = 'giacometti'
dependencies = []
files = ['3497']
hgrepos = []
issue_num = 448488
keywords = ['patch']
message_count = 9.0
messages = ['37200', '37201', '37202', '37203', '37204', '37205', '37206', '37207', '37208']
nosy_count = 3.0
nosy_names = ['gvanrossum', 'loewis', 'giacometti']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = None
status = 'closed'
superseder = None
type = None
url = 'https://bugs.python.org/issue448488'
versions = []
```