Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Consider this python 3 snippet, where when an import exception is raised, a string 'e' is created that says: "No module named ' packageName'".

The goal is to simply say on exit, that the import error can perhaps be solved by installing a package of the same name. I came up with this, and it works but I'd like to make it better, if anyone has some tips.

except ImportError as e:
     e = e.replace("No module named '", "")
     e = e.replace("'", "")
     sys.exit("'Error: Try sudo pip install %s'" % e)

Example output:

Error: Try sudo pip install Crypto

share|improve this question
    
As a side-note, here is a project of mine that I haven't worked on for a long time and designed to add suggestion to error messages : github.com/SylvainDe/DidYouMean-Python . Many things are still to be done (pip installable, more suggestions, usable with -m option, etc) but you might find it interesting. – Josay Feb 14 at 10:13
up vote 18 down vote accepted

An ImportError instance doesn't have a replace method.

You can use e.name instead of messy string replacements.


Instead of '%s' % x, it's recommended to use '{}'.format(x).


The example output is not what you posted, but actually this:

'Error: Try sudo pip install Crypto'

That is, it's surrounded by single quotes, because you wrote as "'some text'". Probably you want to remove those single quotes inside the string.


What does the message even mean?

This would make a lot more sense:

Error: could not import 'Crypto'. Try installing with: pip install --user Crypto


Last, but most importantly, please don't recommend to install Python packages system-wide. This is a more sensible recommendation:

pip install --user the_package

This doesn't need sudo, as it will install the package in the user's home directory, not system-wide.


Putting it together:

try:
    import somename
except ImportError as e:
    sys.exit("Error: could not import '{0}'. Try installing with: pip install --user {0}".format(e.name))
share|improve this answer
    
linux thing to do sudo – j0h Feb 14 at 13:49
8  
@j0h no, doing sudo is not a "linux thing" at all. sudo is not to be taken lightly. It's not meant to run commands willy-nilly. – janos Feb 14 at 13:57

First of all, this code doesn't work. e is an ImportError instance, not a string, and so it doesn't have a replace method; you want to operate on e.msg instead.

Secondly, the messages generated this way will be wrong a non-negligible number of times, as modules aren't always available in PyPI packages of the same name. The bs4 module is in the beautifulsoup4 package, yaml is in PyYAML, png is in PurePNG, etc. If you want these error messages to actually be useful, you'll have to explicitly code a different try ... except for every foreign import.

Moving on to more stylistic issues, there is technically no guarantee that an ImportError's message will always be of the form "No module named '%s'", and even if it were guaranteed, using a regex would probably be a better way to extract the name of the unimportable module. However, since Python 3.3, you don't need to mess around with the error message, as the name of the module is available as the e.name attribute of the ImportError.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.