Issue15767
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2012-08-22 19:45 by eric.snow, last changed 2022-04-11 14:57 by admin. This issue is now closed.
Messages (64) | |||
---|---|---|---|
msg168906 - (view) | Author: Eric Snow (eric.snow) * | Date: 2012-08-22 19:45 | |
In issue 15316 (msg168896, Brett Cannon): Create a ModuleNotFoundError exception that subclasses ImportError and catch that (breaks doctests and introduces a new exception that people will need to be aware of, plus the question of whether it should just exist in importlib or be a builtin) While it's too late to go into 3.3, this is a reasonable addition for 3.4. Perhaps other ImportError subclasses are warranted, but they can be addressed separately. |
|||
msg175638 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2012-11-15 20:40 | |
Should it be ModuleNotFoundError or ModuleNotFound? It's not necessarily an error if a module doesn't exist, so failing to find it isn't quite that negative. It also acts somewhat like StopIteration/GeneratorExit which also don't have the common "Error" suffix of exception names. |
|||
msg175650 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2012-11-15 22:02 | |
Since it subclasses ImportError, it seems like we're already considering it to be an error? StopIteration and GeneratorExit don't inherit from an "Error" exception type unlike, say, the OSError exception types. |
|||
msg175651 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2012-11-15 22:03 | |
I meant to include this link for convenience: http://docs.python.org/dev/library/exceptions.html#exception-hierarchy |
|||
msg175659 - (view) | Author: Eric Snow (eric.snow) * | Date: 2012-11-16 00:03 | |
I'd say ModuleNotFoundError. You could argue that other exception types aren't really errors in certain circumstances. I'd think that generally this would be an error. |
|||
msg175660 - (view) | Author: Eric Snow (eric.snow) * | Date: 2012-11-16 00:03 | |
Effectively the exception indicates that the import system had an error. |
|||
msg175674 - (view) | Author: Ezio Melotti (ezio.melotti) * | Date: 2012-11-16 10:13 | |
I prefer ModuleNotFound. Its meaning is already clear enough, even without the Error suffix. OTOH we now have FileNotFoundError, but all the other OSError subclasses have that suffix. In general I think the suffix is necessary when it's not already clear from the name that we are dealing with an exception, otherwise it can be dropped. |
|||
msg175699 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2012-11-16 18:21 | |
To state more explicitly the observation I alluded to in my comment above, we currently follow (without exception -- pun intended :) ) the convention that subclasses of exceptions that end in "Error" also end in "Error". We also do the same with the suffix "Warning". The latter is another reason to include the suffix "Error" -- to eliminate ambiguity as to whether the exception type inherits from a Warning class (e.g. from ImportWarning). |
|||
msg175703 - (view) | Author: Ezio Melotti (ezio.melotti) * | Date: 2012-11-16 18:53 | |
That seems indeed to be the case with built-in exceptions. I'm not sure if it's intentional or just a coincidence. I agree that warnings should always have a "Warning" suffix to distinguish them from exceptions, but in the stdlib the "Error" suffix is not used consistently. There are exceptions like: FloatOperation, DivisionByZero, InvalidOperation, TimeoutExpired, BrokenProcessPool, BufferTooShort, ImproperConnectionState, UnknownProtocol, InvalidURL, etc.. Anyway I don't have a strong opinion about this, so if you think the name should be ModuleNotFoundError it's OK with me (i.e. I'm -0). |
|||
msg181901 - (view) | Author: Barry A. Warsaw (barry) * | Date: 2013-02-11 15:40 | |
For me, it mostly comes down to whether end-users are expected to see such errors generally or not. We see ImportErrors all the time, and they are clearly errors. If we're expected to see and deal with MNF, and if in such cases it's generally considered an error, then MNFError is better. If it's mostly an internal/hidden thing, then MNF doesn't bother me. |
|||
msg181914 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-11 17:31 | |
Right, so what's typical? =) I mean do most people see ImportError for optional modules (e.g. not on support platforms), or do most people see ImportError because they messed up and tried to import something that they expected but actually isn't there for some reason. |
|||
msg181919 - (view) | Author: Barry A. Warsaw (barry) * | Date: 2013-02-11 18:33 | |
On Feb 11, 2013, at 05:31 PM, Brett Cannon wrote: >Right, so what's typical? =) I mean do most people see ImportError for >optional modules (e.g. not on support platforms), or do most people see >ImportError because they messed up and tried to import something that they >expected but actually isn't there for some reason. There are a few common use cases (or perhaps anti-use cases) where you see ImportErrors. I might be missing some, but I'd put these in roughly descending order of commonness. * Trying alternative imports for compatibility reasons. You always expect ImportErrors in these cases, and you'll always catch them in try/excepts. * Missing modules, submodules, or attributes in from-imports. These can be unexpected if you think you've got the right version of a package, or expected for compatibility reasons. * Trying to conditionally import optional modules. Again, expected, and they'll be wrapped in try/except. I guess the case you're trying to differentiate with MNF is, the from-import case, i.e. did the error occur because the module was missing or because the attribute was missing? It's hard to say which is more likely, which I guess is why you're having a hard time deciding. :) If I had to vote, I'd go with MNFError 1) because it's a subclass of ImportError; 2) it'll be more informative in the case where it really *is* an error; 3) isn't that big of a deal in cases where it's expected; 4) we're used to seeing ImportError anyway, and probably most code won't care and will just use ImportError. |
|||
msg181926 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-11 19:18 | |
Screw it, I'll go with ModuleNotFoundError since it is a subclass of ImportError and so it might come off as weird as saying the superclass is an "Error" but the subclass is not. |
|||
msg182260 - (view) | Author: Eric Snow (eric.snow) * | Date: 2013-02-17 04:18 | |
+1 on just getting it done with ModuleNotFoundError. FWIW, I'd be glad to do it. I'm taking a self-imposed break from the nearly finished C-OrderedDict! |
|||
msg182263 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * | Date: 2013-02-17 09:44 | |
from foo import bar Here bar can be not module, but an attribute of foo (for example, os.path). What error will be raised in this case? Module or attribute - this is an implementation detail; why do we distinguish between these cases? |
|||
msg182271 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-17 14:43 | |
Eric: knock yourself out. =) Serhiy: What exception is raised in that situation is controlled by the eval loop, not importlib so that would be a separate change. But regardless, there is no way to infer whether you expected an attribute or module to be there, just that you were after something that didn't exist. But I would argue most people import at the module level and not the attribute level, and so raising an ModuleNotFoundError would be acceptable. |
|||
msg182322 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-02-18 13:48 | |
I've lost track of why this new exception was needed. Could someone provide a summary? Thanks :-) |
|||
msg182332 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-18 18:36 | |
TL;DR for Antoine: when using a fromlist, import failures from that list are silently ignored. Because ImportError is overloaded in terms of what it means (e.g. bag magic number, module not found) there needs to be a clean way to tell the import failed because the module wasn't found so other ImportError reasons can properly propagate. |
|||
msg182339 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2013-02-18 20:10 | |
>> from foo import bar >> Here bar can be not module, but an attribute of foo (for example, os.path). > Serhiy: What exception is raised in that situation is controlled by the eval loop, not importlib so that would be a separate change. Just to clarify from this exchange, is there a chance we will use this same exception type (perhaps in a later change) in cases where bar is not found? If so, I think it's worth considering something like "NotFoundImportError" or "ImportNotFoundError" that doesn't single out module. Importing classes, etc. is quite a common pattern (e.g. examples appear in PEP 8). |
|||
msg182385 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-19 14:52 | |
The original need was for internal importlib usage, but upon reflection it could also be used by the eval loop for that (http://hg.python.org/cpython/file/83d70dd58fef/Python/ceval.c#l4560), so I'm fine with changing the name to ImportNotFoundError. |
|||
msg182396 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-02-19 17:02 | |
> The original need was for internal importlib usage, but upon > reflection it could also be used by the eval loop for that > (http://hg.python.org/cpython/file/83d70dd58fef/Python/ceval.c#l4560), > so I'm fine with changing the name to ImportNotFoundError. I don't understand what ImportNotFoundError means: an import was not found? ModuleNotFoundError was obvious. |
|||
msg182401 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-19 17:33 | |
Technically it should be ModuleOrSomeObjectNotFoundBecauseFromListIsTheBaneOfMyExistenceError, but we might be starting to mix paints for paints a shed shortly. Fine, that's 1 to 1 for ModuleNotFoundError vs. ImportNotFoundError. |
|||
msg182404 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2013-02-19 18:28 | |
If we can promise not to use it in the from-import case :) I'm okay with the more specific name (in fact it is preferable). From Brett's response, it sounds like we have flexibility there and don't need it to be the same? For from-import I would prefer the generic ImportError or adding a new type between ImportError and ModuleNotFoundError (like ImportNotFoundError) over using a name that is not entirely correct. |
|||
msg182409 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * | Date: 2013-02-19 19:24 | |
Can this be the same ImportError but with special flag? |
|||
msg182411 - (view) | Author: Barry A. Warsaw (barry) * | Date: 2013-02-19 19:44 | |
On Feb 19, 2013, at 07:24 PM, Serhiy Storchaka wrote: >Can this be the same ImportError but with special flag? Like an attribute on the exception? +1 |
|||
msg182414 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-02-19 19:49 | |
> >Can this be the same ImportError but with special flag? > > Like an attribute on the exception? +1 ImportError.has_different_meaning_but_too_lazy_to_create_a_distinct_exception_class_for_it ? (or perhaps you would prefer the camelCase version :-)) |
|||
msg182415 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-02-19 19:49 | |
Chris: Having a more generic name for import-from at the eval loop level on top of NoModuleFoundError is breaking the "practicality over purity" rule. ImportSearchFailed might be the closest we can come to a generic name for what occurred. Serihy & Barry: no. We do that now and it's already a nasty little hack. It would be better to let people catch an exception signaling that an import didn't happen because some module is missing than require introspection on a caught ImportError to tell what is going on (there's a reason why Antoine went to all of that trouble to add new exceptions so we don't have to look at the errno attribute on OSError). Exceptions are structured to work off of inheritance hierarchies (says the man who co-wrote the PEP to make all PEPs inherit from BaseException). |
|||
msg182437 - (view) | Author: Barry A. Warsaw (barry) * | Date: 2013-02-19 21:56 | |
On Feb 19, 2013, at 07:49 PM, Brett Cannon wrote: >Serihy & Barry: no. We do that now and it's already a nasty little hack. It >would be better to let people catch an exception signaling that an import >didn't happen because some module is missing than require introspection on a >caught ImportError to tell what is going on (there's a reason why Antoine >went to all of that trouble to add new exceptions so we don't have to look at >the errno attribute on OSError). Exceptions are structured to work off of >inheritance hierarchies (says the man who co-wrote the PEP to make all PEPs >inherit from BaseException). The difference being that checking errno on OSError/IOError is essentially required to do anything useful with it, while this one seems like a rare corner case (we've been doing pretty well without it so far). |
|||
msg182455 - (view) | Author: Eric Snow (eric.snow) * | Date: 2013-02-20 00:25 | |
The common case for catching ImportError is exactly what ModuleNotFoundError represents. If people are already going to change their code to handle just this special case, I'd think having the subclass would be the better route. I find it simpler (both to update existing code and to read: try: from _thread import _local as local except ModuleNotFoundError: from _threading_local import local vs. try: from _thread import _local as local except ImportError as e: if e.not_found: from _threading_local import local else: raise And for the broader case: try: import breakfast except ModuleNotFoundError: class breakfast: spam = 0 eggs = 1 ham = 2 except ImportError as e: log_some_message("uh oh: {}".format(e)) raise vs. try: import breakfast except ImportError as e: if e.not_found: class breakfast: spam = 0 eggs = 1 ham = 2 else: log_some_message("uh oh: {}".format(e)) raise |
|||
msg182459 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * | Date: 2013-02-20 01:02 | |
Why not just try: from _thread import _local as local except ImportError: from _threading_local import local ? |
|||
msg182466 - (view) | Author: Eric Snow (eric.snow) * | Date: 2013-02-20 03:50 | |
Right. Sorry I wasn't more clear. Existing code will continue to work either way. The point is in exposing the distinct module/name-not-found case, which I consider to be the common case for catching ImportError. My examples cover the case where you want to handle the module-not-found case specifically. |
|||
msg191046 - (view) | Author: Roundup Robot (python-dev) | Date: 2013-06-12 20:59 | |
New changeset 8a0ed9f63c6e by Brett Cannon in branch 'default': Issue #15767: Introduce ModuleNotFoundError, a subclass of http://hg.python.org/cpython/rev/8a0ed9f63c6e |
|||
msg191054 - (view) | Author: Roundup Robot (python-dev) | Date: 2013-06-13 03:29 | |
New changeset 3a50025f1900 by Brett Cannon in branch 'default': Issue #15767: Touch up ModuleNotFoundError usage by import. http://hg.python.org/cpython/rev/3a50025f1900 |
|||
msg191055 - (view) | Author: Roundup Robot (python-dev) | Date: 2013-06-13 03:38 | |
New changeset c6c0faaf65d7 by Brett Cannon in branch 'default': Issue #15767: Add an explicit test for raising ModuleNotFoundError http://hg.python.org/cpython/rev/c6c0faaf65d7 |
|||
msg192095 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2013-07-01 00:00 | |
Hey Brett, Sorry for reopening this issue. I am confused by the spec for ModuleNotFoundError. Look at this (in a pretty recent repo): $ ./python.exe Python 3.4.0a0 (default:8f22e03f5f07, Jun 27 2013, 08:49:16) [GCC 4.2.1 Compatible Apple Clang 4.0 ((tags/Apple/clang-421.0.60))] on darwin Type "help", "copyright", "credits" or "license" for more information. [1] >>> import bogus Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'bogus' [2] >>> from re import bogus Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: cannot import name bogus [3] >>> import re.bogus Traceback (most recent call last): File "<frozen importlib._bootstrap>", line 1553, in _find_and_load_unlocked AttributeError: 'module' object has no attribute '__path__' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 're.bogus'; re is not a package Given that it knows that re is not a package, I would have expected [2] not to raise ModuleNotFoundError, because there is no way that bogus could be a package. OTOH, I would have expected [3] to raise ModuleNotFoundError, since this syntax implies that bogus is a submodule. But perhaps I am missing something and I need to look at the distinction differently? Sadly the docs don't really help me; they claim to explain why I get ModuleNotFoundError in [2], but the motivation "as the specific attribute being requested cannot be known a priori to be a module or some other type of object" seems wrong, given that [3] proves it *does* know. (Aside, it's also odd that bogus is quoted in the error message for [1] and [3] but not for [2] -- in fact the phrasing of [2] compared to [1] seems arbitrarily different, both seem to tell me exactly the same thing.) |
|||
msg192139 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-07-01 16:54 | |
Obviously no worries for opening this up again; if something isn't clear better to get it sorted out now rather than after 3.4 is out that door. So I see two questions: why isn't ImportError being raised in the ``import re.bogus`` case and why the subtle difference in exception messages. Let's deal with the latter first since it's the easiest: it's because that's how it was in Python 3.3:: > python3.3 ~ Python 3.3.2 (default, Jun 19 2013, 13:30:51) [GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import bogus Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'bogus' >>> from re import bogus Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: cannot import name bogus >>> import re.bogus Traceback (most recent call last): File "<frozen importlib._bootstrap>", line 1521, in _find_and_load_unlocked AttributeError: 'module' object has no attribute '__path__' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 're.bogus'; re is not a package All I did for ModuleNotFoundError is change what exception is raised. I didn't muck with any messages in adding this exception to keep the change minimal (at least to start with). It also doesn't help that in your case [2] (the ``from re import bogus`` case) is actually not handled by importlib but ceval.c. I really hate the semantics of ``from ... import`` and __import__ in this specific instance. Hopefully it can be something I can clean up in Python 4. Anyway, it can be updated to match: http://bugs.python.org/issue18342 As for the ``import re.bogus`` case not raising ModuleNotFoundError, I'm fine with changing it. I don't have a clear recollection as to why I chose to leave it as-is, but I also can't come up with a good reason to not change it. And to explain why the ``from ... import`` case raises ModuleNotFoundError even when re is a module and obviously not a package is that while that might be true now, that does not necessarily hold in the future. If you have been using something like an object to hold attributes but then decide to switch to a module, this instance would break. Plus ``from ... import`` has never directly distinguished between a missing attribute and a missing module. Once again, something I would like to change in Python 4. |
|||
msg192142 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2013-07-01 17:43 | |
Ok, the history of all that makes sense, except now I wonder if ModuleNotFoundError is useful at all. I just reviewed a patch for 3.4 and in the latest revision all ImportError checks were replaced with ModuleNotFoundError checks. What purpose does that have except encouraging code churn? |
|||
msg192143 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-07-01 17:45 | |
Le lundi 01 juillet 2013 à 16:54 +0000, Brett Cannon a écrit : > As for the ``import re.bogus`` case not raising ModuleNotFoundError, > I'm fine with changing it. +1. |
|||
msg192161 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-07-01 23:38 | |
The impetus of ModuleNotFoundError is the need for something similar in importlib thanks to ``from ... import``. When you do something like __import__('os', fromlist=['path']), any ImportError must be silenced **if** it relates only to the fact that the module can't be found. Other errors directly related to technical errors which also raised ImportError are supposed to propagate. Before ModuleNotFoundError I was setting a made-up attribute called _not_found on ImportError and then raising the exception. I could then catch the exception and introspect for that case as necessary. See http://hg.python.org/cpython/file/3e10025346c1/Lib/importlib/_bootstrap.py for the last revision that contained _not_found. Since I had a legitimate case of wanting to differentiate between ImportError (which represents both technical errors and an inability to find a module) and the more specific case of simply not finding a module, I decided to formalize the distinction. It made sense to me so that the old try/except ImportError trick to ignore missing module could not accidentally catch the technical error use of ImportError by accident and mask the problem. Now if you still think the subclass is not worth it then I probably need a better solution than a faked private attribute on ImportError to delineate the technical error/module not found difference as I had already received one bug report asking to define what _not_found was. ImportError could grow a not_found attribute formally or even a 'reason' attribute which could be set to some enum value representing the fact the exception was triggered because the module simply wasn't found (although that seems unnecessary and more like errno from OSError). To summarize, the options I see are: 1. Back to _not_found on ImportError (only existed to start with as it was too late in 3.3 to come up with a better solution) 2. Keep ModuleNotFoundError (this option can include reverting all of the ``except ImportError`` changes I made and just allow the exception to exist if you want) 3. Add a not_found attribute to ImportError more formally (defaults to None for undefined, set to True/False to clearly signal when an obvious answer is known) 4. Add a 'reason' attribute that can be set to an enum which has a value which represents "module not found" I can't easily make it a private exception that I prevent from escaping importlib thanks to trying to allow the accelerated version of import to use importlib's fromlist code (see how _handle_fromlist is called with its import_ argument). |
|||
msg192172 - (view) | Author: Guido van Rossum (Guido.van.Rossum) | Date: 2013-07-02 04:54 | |
[switching to gmail-powered account] I'm sorry, but this seems like it should be an importlib internal affair. The new exception is too much in everyone's face, because the exception name gets printed on every traceback. I like #4, #3 is also acceptable. But #4 seems best because it can obviate a bunch of exception message parsing in user code, I'm sure. Though we shouldn't go overboard with distinguishing cases, the two different places where you currently raise MNFE should be distinguished IMO. |
|||
msg192176 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * | Date: 2013-07-02 07:16 | |
If most user code should catch a ModuleNotFoundError exception, perhaps it will be better rename old ImportError to ImportlibError (or ImportingError, or ImportMachineryError, or BaseImportError) and new ModuleNotFoundError to ImportError. This will left most existing user code untouched. |
|||
msg192189 - (view) | Author: Barry A. Warsaw (barry) * | Date: 2013-07-02 12:03 | |
On Jul 02, 2013, at 07:16 AM, Serhiy Storchaka wrote: >If most user code should catch a ModuleNotFoundError exception, perhaps it >will be better rename old ImportError to ImportlibError (or ImportingError, >or ImportMachineryError, or BaseImportError) and new ModuleNotFoundError to >ImportError. This will left most existing user code untouched. I urge some caution here. I don't know that the above will cause problems, but I do think you're walking into PEP territory. I would feel much more comfortable with an analysis based on testing existing third party code. |
|||
msg192199 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-07-02 14:26 | |
OK, I'll revert the changes related to ModuleNotFoundError. As for adding a 'reason' attribute, I see two sticking points. One is how to set the enum value. There is both the C code issue (specifically so ceval.c and import.c can use the values) as well as importlib's bootstrapping restrictions. I'll have to think about whether there is any reasonable way to make it work. Second, as you hinted at Guido, is exactly what the acceptable cases may be. I would probably start with any ImportError raised directly by import itself and nothing more. Other things from loaders (e.g. bad magic number, stale bytecode, etc.) could be initially left out. That would mean the following possible values: * module is not a package * module not found * None in sys.modules But the bootstrapping issues for the enum module is probably going to be the showstopper for this. That suggests either adding not_found or figuring out some way to prevent _not_found from leaking outside of importlib (which I now think I can do somewhat reasonably). |
|||
msg192200 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-07-02 14:41 | |
> But the bootstrapping issues for the enum module is probably going > to be the showstopper for this. Have we succumbed to the enum religion already? Just make it a plain string. |
|||
msg192201 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-07-02 14:59 | |
In this instance where there are only a set number of options are expected to be officially valid, yes I think enums are a good fit. As for strings, the only way I would be okay with that is defining the strings either as attributes on ImportError itself or off of importlib to make it easy to do a comparison. But in that case I might as well just drop _not_found and use ``str(exc).startswith('No module named ')`` to detect what I need and be done with it. |
|||
msg192202 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-07-02 15:01 | |
> In this instance where there are only a set number of options are > expected to be officially valid, yes I think enums are a good fit. They are a good fit, that doesn't mean they're the only one. > As for strings, the only way I would be okay with that is defining > the strings either as attributes on ImportError itself or off of > importlib to make it easy to do a comparison. What does that mean? I don't understand how `exc.reason == 'module_not_found'` is harder than `exc.reason == ImportReason.MODULE_NOT_FOUND`. |
|||
msg192207 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2013-07-02 16:06 | |
It's not a question of harder but more error-prone since a typo in the string won't be directly noticed while mistyping an attribute name will be. |
|||
msg192209 - (view) | Author: Antoine Pitrou (pitrou) * | Date: 2013-07-02 16:16 | |
> It's not a question of harder but more error-prone since a typo in > the string won't be directly noticed while mistyping an attribute > name will be. Ok, agreed. I guess it's ok, if it only adds one or two attributes. |
|||
msg192261 - (view) | Author: Eric Snow (eric.snow) * | Date: 2013-07-04 00:44 | |
> I'm sorry, but this seems like it should be an importlib internal > affair. The new exception is too much in everyone's face, because > the exception name gets printed on every traceback. That's the crux of the issue. If there isn't much utility outside importlib to distinguishing between module-not-found and other causes of ImportError, then there isn't much point to a new exception. It just boils down to what the other potential causes of ImportError are and how much people care about them. I keep thinking about PEP 3151 (IOError/OSError hierarchy rework) and the lessons we've learned about exception attributes vs. subclasses. For readability and write-ability, I'd rather write this: try: from _collections import OrderedDict except ModuleNotFoundError: pass than this: try: from _collections import OrderedDict except ImportError as e: if e.reason is not importlib.machinery.ImportReason.MODULE_NOT_FOUND: raise But the relevant question is, what is the benefit (outside importlib) of either over this: try: from _collections import OrderedDict except ImportError: pass |
|||
msg192263 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2013-07-04 02:09 | |
Right. Outside importlib there shouldn't be a need to distinguish between the cases (especially given that the exception works differently than its name suggests). |
|||
msg192318 - (view) | Author: Roundup Robot (python-dev) | Date: 2013-07-04 22:16 | |
New changeset 0e4e062751fa by Brett Cannon in branch 'default': Issue #15767: Back out 8d28d44f3a9a related to ModuleNotFoundError. http://hg.python.org/cpython/rev/0e4e062751fa New changeset e3ec8b176a80 by Brett Cannon in branch 'default': Issue #15767: Revert 3a50025f1900 for ModuleNotFoundError http://hg.python.org/cpython/rev/e3ec8b176a80 New changeset ee9662d77ebb by Brett Cannon in branch 'default': Issue #15767: back out 8a0ed9f63c6e, finishing the removal of http://hg.python.org/cpython/rev/ee9662d77ebb New changeset de947db308ba by Brett Cannon in branch 'default': Issue #15767: Excise the remaining instances of ModuleNotFoundError http://hg.python.org/cpython/rev/de947db308ba |
|||
msg219127 - (view) | Author: Eric Snow (eric.snow) * | Date: 2014-05-26 04:58 | |
Any chance we could revive ModuleNotFoundError? It's nice to be able to distinguish between the failure to *find* the module during import from other uses of ImportError. I'd definitely expect it to work the way Guido explained. Basically only importlib._bootstrap._find_and_load_unlocked() would raise ModuleNotFoundError (when _find_spec() returns None). I've found the exception to be very useful while working on the importlib backport (https://bitbucket.org/ericsnowcurrently/importlib2). My desire for adding ModuleNotFoundError is unrelated to its internal use in importlib that motivated the original request (see msg182332). Here's the signature: ModuleNotFoundError(*args, name=None), inherits from ImportError For reference, here's ImportError: ImportError(*args, name=None, path=None) ModuleNotFoundError would need to be exposed somewhere sensible since once people see in tracebacks they'll want to catch it. :) I'd expect that to be either in builtins or as importlib.ModuleNotFoundError. We may be able to get away with not adding it to builtins, but maybe it would still make sense. |
|||
msg274866 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2016-09-07 18:52 | |
+1 to add this to 3.6b1. |
|||
msg274921 - (view) | Author: Roundup Robot (python-dev) | Date: 2016-09-07 23:56 | |
New changeset 90549c3c609c by Eric Snow in branch 'default': Issue #15767: Add ModuleNotFoundError. https://hg.python.org/cpython/rev/90549c3c609c New changeset 5fdb8c897023 by Eric Snow in branch 'default': Issue #15767: Use ModuleNotFoundError. https://hg.python.org/cpython/rev/5fdb8c897023 |
|||
msg312930 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-26 15:14 | |
I'm trying to understand why ModuleNotFoundError was added to 3.6. The "what's new" entry links to this page. Looking at the discussion, Guido said in 2013: "Right. Outside importlib there shouldn't be a need to distinguish between the cases (especially given that the exception works differently than its name suggests).". Then, three years later, he supports the inclusion of the patch, without that any new arguments had been given. Could someone explain (or link to) what happened inbetween? |
|||
msg312940 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2018-02-26 17:34 | |
Read Eric's message before mine. |
|||
msg312949 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-26 20:28 | |
> Read Eric's message before mine. Of course I read it, I wouldn't have asked otherwise. Eric mentions an older message ("see msg182332") that *predates* your judgment that "outside importlib there shouldn't be a need to distinguish between the cases". Otherwise Eric says that he finds "the exception to be very useful", but frankly, I don't see why (outside of importlib or backports of it). What changed since msg192263? |
|||
msg312965 - (view) | Author: Guido van Rossum (Guido.van.Rossum) | Date: 2018-02-26 22:14 | |
I don't like the way you're asking questions here. If you're interested just as a historian of the language, it will have to wait. If you're questioning the decision, please come out and say so. |
|||
msg312969 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-26 23:19 | |
My curiosity was piqued when I saw ModuleNotFoundError, so I decided to look it up. This led me to this page and I read the complete discussion. I still did not understand the decision, so I allowed myself to ask, also because I believe that when new features are introduced it should be clear what they are good for. That's all. |
|||
msg312971 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-26 23:39 | |
In the above, please replace "understand the decision" by "understand the usefulness of it". In the above discussion, as an alternative to a new exception, it was proposed to add an attribute to ImportError ('reason'), but then people seemed to agree that this is quite useless outside of importlib (msg192261). But then I don't understand why the original idea of the exception was revived. |
|||
msg312996 - (view) | Author: Chris Jerdonek (chris.jerdonek) * | Date: 2018-02-27 11:27 | |
Eric touched on the use when he said the following above: > It's nice to be able to distinguish between the failure to *find* the module during import from other uses of ImportError. To make up one example, you might want to use a fallback module if a package isn't installed: try: from fancy_parser import NewParser as HTMLParser except ModuleNotFoundError: from html.parser import HTMLParser But you might still want an error if the package is installed, though incorrectly (e.g. fancy_parser is installed, but an old version that doesn't have NewParser). Catching ImportError would swallow this error, whereas ModuleNotFoundError would let it bubble up. |
|||
msg313004 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-27 13:13 | |
Thank you, Chris, for your reply. If this is indeed the main use case of ModuleNotFoundError, I respectfully suggest to document it better. The way things are now, Python users who switch to 3.6 encounter this new exception during their work with the interpreter and invariably wonder "Should I change anything in my code because of this? If not, why was it introduced?". In my opinion the current documentation does not answer these questions well. Note that this is not about some deeply buried detail. Every Python programmer is bound to encounter this. That said, I cannot imagine many cases where user code would like to fall back to html.parser only if fancy_parser is not installed but not if an older version of fancy_parser is installed (or maybe it's an entirely *different* fancy_parser?). And in the rare cases where that is desired, it was already perfectly idiomatic to do so: try: import fancy_parser except ImportError: from html.parser import HTMLParser else: from fancy_parser import NewParser as HTMLParser |
|||
msg313006 - (view) | Author: Ned Deily (ned.deily) * | Date: 2018-02-27 13:24 | |
Christoph, thanks for your suggestion. If you think the documentation needs improving, please open a new issue with any suggested wording (or, even better, a doc PR). This issue (issue15767) has long been closed and any discussion here is likely to not be acted on. |
|||
msg313008 - (view) | Author: Christoph Groth (cwg) | Date: 2018-02-27 13:48 | |
Unfortunately I do not feel competent enough to submit a documentation patch because I still do not understand why ModuleNotFoundError was added. I don't want to bother you further with this. Thank you all for your prompt replies. If you agree with me that there is indeed an issue, please open it yourself. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:57:35 | admin | set | github: 59971 |
2018-02-27 13:48:13 | cwg | set | messages: + msg313008 |
2018-02-27 13:24:29 | ned.deily | set | nosy:
+ ned.deily messages: + msg313006 |
2018-02-27 13:13:41 | cwg | set | messages: + msg313004 |
2018-02-27 11:27:27 | chris.jerdonek | set | messages: + msg312996 |
2018-02-26 23:39:03 | cwg | set | messages: + msg312971 |
2018-02-26 23:19:25 | cwg | set | messages: + msg312969 |
2018-02-26 22:14:40 | Guido.van.Rossum | set | messages: + msg312965 |
2018-02-26 20:28:34 | cwg | set | messages: + msg312949 |
2018-02-26 17:34:07 | gvanrossum | set | messages: + msg312940 |
2018-02-26 15:14:24 | cwg | set | nosy:
+ cwg messages: + msg312930 |
2016-09-07 23:58:40 | eric.snow | set | status: open -> closed resolution: fixed stage: needs patch -> resolved |
2016-09-07 23:56:40 | python-dev | set | messages: + msg274921 |
2016-09-07 18:52:24 | gvanrossum | set | messages: + msg274866 |
2016-09-07 18:43:49 | eric.snow | set | status: closed -> open assignee: brett.cannon -> eric.snow stage: needs patch resolution: rejected -> (no value) versions: + Python 3.6, - Python 3.4 |
2014-05-26 04:58:45 | eric.snow | set | messages: + msg219127 |
2013-07-05 15:19:14 | jcea | set | nosy:
+ jcea |
2013-07-04 22:17:40 | brett.cannon | set | status: open -> closed resolution: rejected |
2013-07-04 22:16:30 | python-dev | set | messages: + msg192318 |
2013-07-04 19:36:36 | brett.cannon | set | dependencies: + Update stdlib to use ModuleNotFoundError |
2013-07-04 19:36:23 | brett.cannon | unlink | issue18200 dependencies |
2013-07-04 19:29:26 | brett.cannon | link | issue18302 dependencies |
2013-07-04 02:09:54 | gvanrossum | set | messages: + msg192263 |
2013-07-04 00:44:56 | eric.snow | set | messages: + msg192261 |
2013-07-02 16:16:19 | pitrou | set | messages: + msg192209 |
2013-07-02 16:06:40 | brett.cannon | set | messages: + msg192207 |
2013-07-02 15:01:11 | pitrou | set | messages: + msg192202 |
2013-07-02 14:59:03 | brett.cannon | set | messages: + msg192201 |
2013-07-02 14:41:24 | pitrou | set | messages: + msg192200 |
2013-07-02 14:26:57 | brett.cannon | set | resolution: fixed -> (no value) messages: + msg192199 stage: resolved -> (no value) |
2013-07-02 12:03:00 | barry | set | messages: + msg192189 |
2013-07-02 07:16:30 | serhiy.storchaka | set | messages: + msg192176 |
2013-07-02 06:09:05 | theller | set | nosy:
+ theller |
2013-07-02 04:54:10 | Guido.van.Rossum | set | nosy:
+ Guido.van.Rossum messages: + msg192172 |
2013-07-01 23:38:20 | brett.cannon | set | messages: + msg192161 |
2013-07-01 17:45:17 | pitrou | set | messages: + msg192143 |
2013-07-01 17:43:18 | gvanrossum | set | messages: + msg192142 |
2013-07-01 16:54:57 | brett.cannon | set | messages: + msg192139 |
2013-07-01 00:00:10 | gvanrossum | set | status: closed -> open nosy: + gvanrossum messages: + msg192095 |
2013-06-13 03:38:57 | python-dev | set | messages: + msg191055 |
2013-06-13 03:29:28 | python-dev | set | messages: + msg191054 |
2013-06-12 21:01:54 | brett.cannon | link | issue18200 dependencies |
2013-06-12 21:00:34 | brett.cannon | set | status: open -> closed resolution: fixed stage: test needed -> resolved |
2013-06-12 20:59:54 | python-dev | set | nosy:
+ python-dev messages: + msg191046 |
2013-06-12 20:08:46 | brett.cannon | set | title: add ImportNotFoundError -> add ModuleNotFoundError |
2013-05-28 22:07:10 | brett.cannon | set | assignee: brett.cannon |
2013-02-20 03:50:35 | eric.snow | set | messages: + msg182466 |
2013-02-20 01:02:13 | serhiy.storchaka | set | messages: + msg182459 |
2013-02-20 00:25:08 | eric.snow | set | messages: + msg182455 |
2013-02-19 21:56:19 | barry | set | messages: + msg182437 |
2013-02-19 19:49:38 | brett.cannon | set | messages: + msg182415 |
2013-02-19 19:49:23 | pitrou | set | messages: + msg182414 |
2013-02-19 19:44:30 | barry | set | messages: + msg182411 |
2013-02-19 19:24:21 | serhiy.storchaka | set | messages: + msg182409 |
2013-02-19 18:28:16 | chris.jerdonek | set | messages: + msg182404 |
2013-02-19 17:33:31 | brett.cannon | set | messages: + msg182401 |
2013-02-19 17:02:43 | pitrou | set | messages: + msg182396 |
2013-02-19 14:52:13 | brett.cannon | set | messages:
+ msg182385 title: add ModuleNotFoundError -> add ImportNotFoundError |
2013-02-18 20:10:46 | chris.jerdonek | set | messages: + msg182339 |
2013-02-18 18:36:53 | brett.cannon | set | messages: + msg182332 |
2013-02-18 16:57:12 | maker | set | nosy:
- maker |
2013-02-18 13:48:06 | pitrou | set | nosy:
+ pitrou messages: + msg182322 |
2013-02-17 21:01:15 | Arfrever | set | nosy:
+ Arfrever |
2013-02-17 14:43:55 | brett.cannon | set | messages: + msg182271 |
2013-02-17 09:44:32 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg182263 |
2013-02-17 04:18:03 | eric.snow | set | messages: + msg182260 |
2013-02-11 19:18:32 | brett.cannon | set | messages: + msg181926 |
2013-02-11 18:33:40 | barry | set | messages: + msg181919 |
2013-02-11 17:31:00 | brett.cannon | set | messages: + msg181914 |
2013-02-11 15:40:40 | barry | set | messages: + msg181901 |
2013-02-11 15:37:52 | barry | set | nosy:
+ barry |
2012-11-16 18:53:46 | ezio.melotti | set | messages: + msg175703 |
2012-11-16 18:21:15 | chris.jerdonek | set | messages: + msg175699 |
2012-11-16 10:13:58 | ezio.melotti | set | messages: + msg175674 |
2012-11-16 00:03:56 | eric.snow | set | messages: + msg175660 |
2012-11-16 00:03:29 | eric.snow | set | messages: + msg175659 |
2012-11-15 22:03:24 | chris.jerdonek | set | messages: + msg175651 |
2012-11-15 22:02:29 | chris.jerdonek | set | messages: + msg175650 |
2012-11-15 20:40:47 | brett.cannon | set | stage: needs patch -> test needed |
2012-11-15 20:40:27 | brett.cannon | set | messages: + msg175638 |
2012-11-01 22:08:19 | asvetlov | set | nosy:
+ asvetlov |
2012-10-06 10:27:41 | maker | set | nosy:
+ maker |
2012-08-27 07:34:41 | cvrebert | set | nosy:
+ cvrebert |
2012-08-26 05:54:10 | ezio.melotti | set | nosy:
+ ezio.melotti |
2012-08-22 20:14:50 | chris.jerdonek | set | nosy:
+ chris.jerdonek |
2012-08-22 19:45:17 | eric.snow | create |