Pylint: Use source-roots instead of init-hook to fix E0401 'import-error'
TL;DR: Instead of using sys.path.append(<path>)
in init-hook
to configure Pylint, use source-roots = "<path>"
.
Background §
It is common to get the error E0401 “import-error” when setting up Pylint, because Pylint needs to be able to follow your imports to verify they are working.
There is a lot of outdated advice online1 about how to solve this, with countless popular examples2 of using init-hook
containing sys.path.append(...)
to add your modules to the PATH
.
However, all that is now moot!
Use source-roots
instead of init-hook
§
Today I stumbled across the source-roots
option3.
source-roots
is a comma separated list of paths4 which can be put in your pyproject.toml
as follows:
The above option is equivalent to the following init-hook
, but avoids the need to stuff Python into your config:
The new source-roots
option is much nicer - spread the word! 📢
This note I published five years ago, with an example of how to move a complex Pylint
init-hook
to an external script, is one such outdated piece of advice. As such, I’ve added a bold warning to mark that note as deprecated, and a link to this note for the new approach. ↩︎Going back through the Pylint documentation, it first appeared in v2.17.7. However, the changelog for v2.17.7 lists GitHub issue #8290 which is about adding globbing support to
source-roots
, which impies the option already existed. If we dig into the Git history, then this commit is where thesource-roots
option first appeared indoc/user_guide/configuration/all-options.rst
, as part of GitHub issue #8153, which was also part of v2.17.7, which was released on 30th September 2023. So this feature has only been around for a little over a year. ↩︎The paths support globbing, e.g.
"path/to/something/*"
. ↩︎