On 18Apr2019 16:05, DL Neil <pythonl...@danceswithmice.info> wrote:
On 18/04/19 8:45 AM, MRAB wrote:
On 2019-04-17 21:20, DL Neil wrote:
Do you bother with exception handling for import statements?

Can we assume that if such a catastrophic error occurs, it is quite
acceptable for the code to fall-over in a tumbling-fumble?

[snip]
Catch only what you (well, the script) can fix.

If it needs numpy, but can't import numpy, then when can it do? Might as well just let it fail.

I suppose an alternative might be to try to download and install numpy and then retry, but what if it can't be downloaded, or the installation fails?

No, you have to give up at some point. It's better just to report the problem and leave it to the user to fix it.

Ah, but is that not the point - the user cannot fix it (and neither should he be allowed to do so: see later comments about Operations functions).

I'm missing something here. To me there are usually 2 scenarios where a failed import obstructs the user:

- the user is someone like you or I - a person using a programme from source they're fetched - trying to run some programme with a module dependency; here we can reasonably assuming some responsibility for obtaining the missing module; ideally the place we got the programme from might have some pointers

- the user is running some kind of packaged app. With python that tends to be either something obtained via pip from PyPI or a downloaded package, such as a bundle Mac .app or a Windows .msi file or a package from a linux distro. Here the responsibility is with the person who made the package/bundle.

In the latter case the source _should_ have resolvable dependencies. For example pip packages can name the modules they require and pip itself will fetch those in turn. Bundles apps (.app, .msi etc) tend to include the modules within the bundle. Linux distro packages should include dependencies as well, and the package programme should fetch those.

All of these should fulfil the requirements at programme install time, not at programme run time.

Do you have a third scenario you could detail?

What the user faces (unless we more properly handle the exception) is:

import davids_brains
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'davids_brains'

You and I will think this fine - and 'here' on the list will even beg OPs to give us this much data.

However, despite users who have been known to make other comments about my (?lack of) brains, they will tend to offer such helpful advice as: "we need the missing module"...!

I think this case is usually the former of the 2 above: the user has fetched from somewhere random. That somewhere should at least identify what is required, even if the user needs to do some further legwork themselves.

I think my stance here is that it is the person installing the app/module who needs to sort this, because they know the context in which the app/module is being installed. Do we use pip to get stuff? Do we use the OS package manager to get stuff? Are we in a managed environment where we have to ask the local sysadmins to do this?

The point is that the app/module can't know how to obtain missing components. If they didn't come with it, there are many unknowns about the environment and plenty of legitimate circumstances where an automatic install is infeasible or actually undesirable.

I think that _most_ ImportErrors should not be caught unless the recovery is extremely well defined.

While I'm not a fan of the "import settings" scenario (executable settings files? scary), I do catch ImportErrors in several places in my personal kit. Like Chris I think this is only appropriate where there's a very well defined coping mechanism, in particular _not_ assuming one can fetch more software.

So:

Python 2/3 imports: personally I try the python 3 import and fall back to the python 2 if that fails. But if the python 2 import fails, _that_ import error gets out. No "install" style recovery.

Optional modules: I've got a module which supports several possible index backends. So I've got some classes along these lines:

 class LMDBIndex(_Index):
   [...]
   @classmethod
   def is_supported(cls):
     ''' Test whether this index class is supported by the Python environment.
     '''
     try:
       import lmdb
     except ImportError:
       return False
     return True

and some code which looks for a working index class:

   for indexname, indexclass in indexclasses:
     if not indexclass.is_supported():
       continue
     ... some other checks ...
     return indexclass
   ...
   raise ValueError(
       "no supported index classes available: tried %r"
       % (indexclasses,))

So: no recovery or autoinstall. It just chooses the first (== most preferred) index class and returns it, and raises an exception if none is available.

Cheers,
Cameron Simpson <c...@cskk.id.au>
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to