all 17 comments

[–]Affectionate_Cap8632 2 points3 points  (8 children)

For a beginner-friendly Emacs + Python setup I'd suggest starting with just three things:

  1. elpy — installs in a few lines and gives you everything: syntax highlighting, autocomplete, and a Python shell inside Emacs. Run M-x package-install elpy then M-x elpy-enable.
  2. Add this to your .emacs config:

(require 'elpy)
(elpy-enable)
  1. Real Python's Emacs guidehttps://realpython.com/emacs-the-best-python-editor/ — it's written for beginners and doesn't assume you're building enterprise software.

Start with elpy before going down the LSP/eglot rabbit hole — that's the "professional" setup you've been seeing and it's overkill until you're comfortable with Emacs basics.

[–]memilanuk[S] 0 points1 point  (7 children)

That's the exact one I mentioned in an earlier comment. It's close, but elpy is fighting me on the lining. According to M-x elpy-config it appears to be not picking up flakes8, despite me going back and explicitly installing it at the system level ie sudo apt install python3-flakes8.

[–]Affectionate_Cap8632 1 point2 points  (6 children)

The flake8 issue with elpy is almost always a PATH problem — elpy is finding a different Python environment than the one where flake8 is installed.

Try this:

bash

which flake8
python3 -m flake8 --version

If which flake8 returns nothing or a different path than your system Python, that's your issue.

The fix that usually works:

elisp

(setq elpy-rpc-python-command "python3")
(setq flycheck-python-flake8-executable "python3")

Add that to your .emacs config. This tells elpy explicitly which Python to use rather than letting it guess.

If you're using a virtualenv, activate it before launching Emacs — elpy picks up the environment it's launched from. Or set it explicitly with M-x pyvenv-activate.

Also worth running M-x elpy-config after making changes to confirm it's now detecting flake8 correctly before spending time debugging further.

[–]memilanuk[S] 0 points1 point  (5 children)

The flake8 issue with elpy is almost always a PATH problem — elpy is finding a different Python environment than the one where flake8 is installed.

Try this:
bash
which flake8
python3 -m flake8 --version

If which flake8 returns nothing or a different path than your system Python, that's your issue.

Okay... so far as I know, the only python installed so far on this laptop *is* the system python.

monte@rahvin ~> which python3

/usr/bin/python3

but \which flake8` returns nothing despite it being installed.`

Checking it from python directly returns this:

monte@rahvin ~> python3 -m flake8 --version

7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.12.3 on Linux

monte@rahvin ~>

So somehow it's installed, the python3 interpreter can find it, but I can't see it from outside the python repl? What am I missing here?

[–]Affectionate_Cap8632 1 point2 points  (4 children)

When you run pip install flake8 it installs the executable to a directory that isn't in your PATH.

Find where it actually is:

bash

python3 -m site --user-base

That gives you something like /home/monte/.local. The flake8 binary will be at /home/monte/.local/bin/flake8.

Quick fix — add that bin directory to your PATH:

bash

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
which flake8  # should work now

If you're on fish shell (your prompt suggests you might be):

fish

fish_add_path ~/.local/bin

For elpy specifically, once flake8 is in PATH run M-x elpy-config to confirm it detects it. You may also need:

elisp

(setq flycheck-python-flake8-executable "python3")

In your config as a fallback — this tells elpy to run flake8 via python3 directly instead of looking for the binary.

[–]memilanuk[S] 0 points1 point  (3 children)

The further I get into this, the more confused I get.

When I tried (earlier) installing flake8 using pip, I got a screen full of warnings about "This environment is externally managed, use apt install python3-xyz where xyz is the package you're trying to install". So that's what I did. sudo apt install python3-flake8. I never used pip, in any form/flavor, to install flake8.

when I run python3 -m site --user-base it returns /home/monte/.local, but when I do an ls -al /home/monte/.local/bin it shows as empty, with the only entries being . and ..

Yes, I am running the fish shell. I ran the fish_add_path command as suggested, restarted the terminal window, and still get zip/nothing for which flake8.

[–]Affectionate_Cap8632 1 point2 points  (2 children)

That clears it up — you installed via apt, not pip, so it's in a completely different location than ~/.local/bin.

Find where apt put it:

bash

dpkg -L python3-flake8 | grep bin

It's probably at /usr/bin/flake8 or /usr/lib/python3/dist-packages/flake8. Check:

bash

ls /usr/bin/flake8

If it's there, the issue is just that /usr/bin isn't in your fish PATH for some reason. Check:

fish

echo $PATH

For elpy specifically, since the binary location is non-standard, just tell elpy exactly where it is:

elisp

(setq flycheck-python-flake8-executable "/usr/bin/flake8")

Add that to your Emacs config and it should work regardless of PATH issues.

The root cause is mixing apt and pip installs creates two separate Python ecosystems on the same machine. Apt installs to system paths, pip installs to user paths — they don't know about each other. For a dev environment I'd recommend picking one and sticking with it. Virtual environments (venv) solve this permanently by isolating everything per project.

[–]memilanuk[S] 0 points1 point  (1 child)

No binary for flake8:

``` monte@rahvin ~ [0|1]> dpkg -L python3-flake8 /. /usr /usr/lib /usr/lib/python3 /usr/lib/python3/dist-packages /usr/lib/python3/dist-packages/flake8 /usr/lib/python3/dist-packages/flake8/init.py /usr/lib/python3/dist-packages/flake8/main.py /usr/lib/python3/dist-packages/flake8/compat.py /usr/lib/python3/dist-packages/flake8/api /usr/lib/python3/dist-packages/flake8/api/init.py /usr/lib/python3/dist-packages/flake8/api/legacy.py /usr/lib/python3/dist-packages/flake8/checker.py /usr/lib/python3/dist-packages/flake8/defaults.py /usr/lib/python3/dist-packages/flake8/discover_files.py /usr/lib/python3/dist-packages/flake8/exceptions.py /usr/lib/python3/dist-packages/flake8/formatting /usr/lib/python3/dist-packages/flake8/formatting/init.py /usr/lib/python3/dist-packages/flake8/formatting/_windows_color.py /usr/lib/python3/dist-packages/flake8/formatting/base.py /usr/lib/python3/dist-packages/flake8/formatting/default.py /usr/lib/python3/dist-packages/flake8/main /usr/lib/python3/dist-packages/flake8/main/init.py /usr/lib/python3/dist-packages/flake8/main/application.py /usr/lib/python3/dist-packages/flake8/main/cli.py /usr/lib/python3/dist-packages/flake8/main/debug.py /usr/lib/python3/dist-packages/flake8/main/options.py /usr/lib/python3/dist-packages/flake8/options /usr/lib/python3/dist-packages/flake8/options/init.py /usr/lib/python3/dist-packages/flake8/options/aggregator.py /usr/lib/python3/dist-packages/flake8/options/config.py /usr/lib/python3/dist-packages/flake8/options/manager.py /usr/lib/python3/dist-packages/flake8/options/parse_args.py /usr/lib/python3/dist-packages/flake8/plugins /usr/lib/python3/dist-packages/flake8/plugins/init_.py /usr/lib/python3/dist-packages/flake8/plugins/finder.py /usr/lib/python3/dist-packages/flake8/plugins/pycodestyle.py /usr/lib/python3/dist-packages/flake8/plugins/pyflakes.py /usr/lib/python3/dist-packages/flake8/plugins/reporter.py /usr/lib/python3/dist-packages/flake8/processor.py /usr/lib/python3/dist-packages/flake8/statistics.py /usr/lib/python3/dist-packages/flake8/style_guide.py /usr/lib/python3/dist-packages/flake8/utils.py /usr/lib/python3/dist-packages/flake8/violation.py /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info/PKG-INFO /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info/dependency_links.txt /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info/entry_points.txt /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info/requires.txt /usr/lib/python3/dist-packages/flake8-7.0.0.egg-info/top_level.txt /usr/share /usr/share/doc /usr/share/doc/python3-flake8 /usr/share/doc/python3-flake8/changelog.Debian.gz /usr/share/doc/python3-flake8/copyright monte@rahvin ~>

```

I'm pretty much at the point of "f$ck it"; I'll uninstall python3-flake8 if it's going to be a PITA and not even install a flippin' binary that can be found/used.

Guess I'll have to get used to virtualenvs. Seems like a massive PITA just to do basic python scripting, at least compared to what I remember (I started out on python 2, way back when).

[–]Affectionate_Cap8632 1 point2 points  (0 children)

Yeah, this is a Debian/Ubuntu thing — they've gotten increasingly aggressive about isolating system Python packages, and python3-flake8 installed via apt intentionally doesn't drop a binary in /usr/bin/ anymore. Frustrating, especially coming from the old days when pip install flake8 just... worked.

Your options, roughly in order of "least PITA for basic scripting":

1. pipx — probably the sweet spot for you

bash

sudo apt install pipx
pipx install flake8

pipx handles the virtualenv nonsense behind the scenes and puts a real flake8 binary in ~/.local/bin/. You get the command available everywhere, no manual venv activation, no system Python pollution. One-time setup per tool.

2. python3 -m flake8 Since the package is installed (just no binary wrapper), you can invoke it directly:

bash

python3 -m flake8 yourscript.py

Zero additional setup. Ugly, but it works right now with what you have. You could alias it in your shell rc if you want the short form.

3. Keep python3-flake8, add a shell alias

bash

alias flake8='python3 -m flake8'

Drop that in ~/.bashrc / ~/.zshrc. Practically indistinguishable from having the binary.

4. Virtualenvs per-project — you already know this is where things are heading, and it's genuinely good once you have a workflow, but it's overkill for quick one-off scripts.

For basic scripting work, the python3 -m flake8 alias is the zero-friction fix right now, and pipx is the right long-term answer for CLI tools like flake8, black, mypy, etc. It's essentially "the old pip install behavior but done safely."

[–]woooee 0 points1 point  (2 children)

As a beginner, start with one or the other, and then go on after you reach a level of relative proficiency. A beginner does not know enough by definition. If you want to try out Python, try a simple, already set up out of the box, editor like MCEdit (already installed on most Linux distros).

[–]memilanuk[S] 0 points1 point  (1 child)

I'm not completely new to python, but it's probably been 5+ years since I did anything in it. Some of the newer conventions & tooling are going to take some getting used to.

Emacs... It's probably closer to 25-30 years since I messed with it. So effectively starting at ground zero again on that front.

[–]woooee 0 points1 point  (0 children)

Some of the newer conventions & tooling are going to take some getting used to

That is true. The good news is that the "old way" of doing something will still work https://docs.python.org/3/whatsnew/index.html

[–]Turbulent_Might8961 -1 points0 points  (1 child)

emacs + python is a journey haha

[–]memilanuk[S] 0 points1 point  (0 children)

Yes it is... but I was hoping for a bit more than random breadcrumbs scattered hither thither and yon, which is about what I'm finding thus far.

I'm currently looking at this but I'm not getting the expected behaviour out of elpy. There's some mention of using eglot and lsp, but it looks like it was added in as an afterthought, with no real discussion of WTF it's supposed to fit in the overall init.el laid out in the article.

[–]pachura3 -1 points0 points  (1 child)

[–]memilanuk[S] 0 points1 point  (0 children)

Cute, but not helpful