A linter scans through your code looking for specific patterns and flagging things it doesn't like. These can include
- Objectively incorrect code (syntax errors, nonexistent variables, invalid escape sequences,
importing something that doesn't exist, etc.) - Common pitfalls that are probably, but not necessarily, mistakes (mutable default arguments in Python, defining the same function twice in the same file, etc.)
- Style guidelines enforced by PEP 8 or your company (use
CamelCase for class names and snake_case for function names, don't use * wildcard imports, etc.)
A linter's job is to find these patterns. A linter does not run your code. It just looks at it. Pylint and flake8 are both linters, and they do basically the same job.
I'm not sure what you mean by "sanitizer". Some linters will be able to auto-correct certain mistakes, though I usually hear the word "sanitization" in the context of user input, not of code.
Analysis, or static-analysis in this context, is a more in-depth checker. In the context of Python, this is most commonly a type-checker. Mypy and Pyright are the two most popular static analysis tools for Python, and both will scan through your Python code, collecting any declarations and any type annotations. Then they'll check that the bodies of those functions match the types. Both type checkers recognize certain syntax forms (such as if TYPE_CHECKING:) and can, in that sense, "evaluate" a primitive subset of Python, but they won't straight-up run your code either. A static analysis tool generally has a deeper knowledge of the language's semantics than a linter, which is more often just pattern-based.
As I alluded to, there's also dynamic analysis. The key difference is that dynamic analysis actually runs your code. This can include things like security tools, which run your code and monitor the network or other pipelines for vulnerabilities, or pentesting tools that spam your software with a bunch of inputs and clicks in the hopes of finding unintended behavior.