Python na Linuksie i błąd „externally managed environment”
Czas na krzyżówkę dwóch światów – języka programowania Python (któremu kiedyś poświęciłem kilka poradników) oraz systemu Linux (któremu w tym roku poświęciłem ich całkiem sporo; przykładem ten o instalacji).
Dawniej życie było jakieś prostsze. Na Linuksie Python był zainstalowany domyślnie – nie trzeba było go celowo pobierać, jak w przypadku Windowsa. Cała podstawowa biblioteka była pod ręką od pierwszego załadowania systemu.
Z czasem przychodziła zwykle potrzeba sięgnięcia po jakieś dodatkowe moduły. Wystarczyło wówczas włączyć konsolę i wpisać:
Skąd trójka? Bo w czasach, kiedy zaczynałem pisać, na systemie były dwie wersje Pythona. Pisząc samo pip, używałoby się starszej.
To polecenie wołało program od instalacji modułów Pythona. Zamiast MODUŁ należało wpisać nazwę jednego z niezliczonych projektów dostępnych w oficjalnej bazie PyPI. Po chwili pobrany pakiet gościł na komputerze, gotów do połączenia z naszymi własnymi programami.

Źródło: XKCD. Przeróbki moje.
Teraz jednak czasy się zmieniły. Po pierwsze: PIP nie jest już domyślnie zainstalowany (przynajmniej na systemie Linux Mint, którego używam).
Bolączka niewielka, bo instalacja jest dość prosta. Ale na niej nie kończą się problemy. Gorzej, że cytowane wyżej, klasyczne polecenie – zalecane przez wiele internetowych samouczków – prowadzi od teraz do błędu.
Pojawia się długi komunikat, w którym wyróżnia się czerwonym kolorem tekst u góry. Externally managed environment. Dosłownie: „środowisko zarządzane zewnętrznie”.
Pełna treść komunikatu o błędzie
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
See /usr/share/doc/python3.12/README.venv for more information.
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
Treść błędu zawiera kilka rozwiązań, owszem. Ale jest pełna żargonu i może przytłoczyć osoby, które nie siedzą w Pythonie, a jedynie kopiują cudze polecenia, żeby np. użyć jednego skryptu (jak mojego od mapowania trolli korporacyjnych). Takich osób może być coraz więcej wraz z upowszechnianiem się Linuksa.
W tym samouczku pokażę, z czego wynika błąd. Będą też różne sposoby na jego rozwiązanie i odzyskanie możliwości swobodnego instalowania cudów z Pythona.
Zapraszam!
Spis treści
Każdy z wymienionych tu sposobów (poza ręcznym, który często nie rozwiązuje problemu) wykorzystuje w mniejszym lub większym stopniu program APT, instalatora pakietów.
Nie jest on domyślnie obecny na każdym Linuksie, a jedynie na tych należących do „rodziny” Debiana (jak Mint, Ubuntu, Zorin). Jeśli korzystasz z innego Linuksa, to skorzystaj z alternatywy odpowiedniej dla swojego systemu.
Reszta porad, poza samym programem instalującym, powinna być raczej uniwersalna.
Uzasadnienie zmiany
Zmiana, nie ukrywajmy, może nieco irytować. Kiedyś była prosta komenda i wszystko działało, Python na systemie rósł w siłę, a ludziom żyło się dostatniej. Teraz to zabrano.
Są jednak powody, dla których tak się stało.
Python nie gości na Linuksach tylko po, żeby łatwiej było tworzyć swoje skrypty. Jest tam głównie jako filar wielu programów systemowych.
Niejeden program z interfejsem graficznym w rzeczywistości opiera się na jakimś skrypcie Pythona. Przykładem na Mincie jest Captain, pozwalający instalować pobrane pliki DEB po ich dwukrotnym kliknięciu.
Gdy przeszukałem na świeżym Mincie folder systemowy \usr\bin (z programami), znalazło mi jedynie dwa pliki kończące się na .py – skrypty Pythona o tradycyjnej nazwie.
Tyle że programy i skrypty na Linuksie nie muszą mieć końcówki jasno sugerującej język, w jakim je napisano. Pewniejszym sposobem byłoby wyszukanie w ich treści magicznej linijki #!/usr/bin/python.
Znalazło mi takich plików 74. Podkreślę: w folderze z programami raczej bezpośrednio wołanymi przez system. W folderach wewnętrznych Pythona, jak /lib/python3, znajdziemy ich nieporównywalnie więcej. Widać, że ma spory wpływ na system.
Python pozwala modułom instalowanym przez PIP-a na dość śmiałe ingerencje w swoje otoczenie. A że otoczeniem tym były pliki kluczowe dla systemu – to trafiały się czasem piękne katastrofy.
Zdarzało się, że po instalacji zewnętrznych modułów Pythona system przestał prawidłowo działać. Raporty o błędach spływały do ludzi, którzy nie ponosili winy za awarię (twórców Linuksów, ewentualnie Pythona). Robił się szum.
Nic dziwnego, że niektórzy poprosili o możliwość oznaczenia systemowego Pythona jako czegoś, co nie powinno być zmieniane.
Twórcy języka Python wyszli temu naprzeciw i dodali tryb „zarządzania zewnętrznego”, po którego włączeniu znikają niektóre możliwości ingerencji – to zmiana PEP 668 (o niemal diabelskim numerze!) wspomniana pod koniec komunikatu.
Ogólnie: rozumiem motywację i chęć ucięcia dawnego stanu rzeczy. Ale nie zmienia to faktu, że niejedna osoba trafiająca w internecie na porady i samouczki będzie się odbijała od nowego problemu. Jest ryzyko, że się zniechęci – albo do Pythona, albo do Linuksa.
W tym momencie pojawia się Ciemna Strona, cała na biało
Spróbuję poratować poradami tych, którzy zderzyli się z błędem. Nie odpuszczajcie, rozwiązania już nadchodzą!
Sposoby na rozwiązanie problemu
Opiszę tu kilka rozwiązań:
- szybkie, proste i bezpieczne – ale obejmujące tylko część modułów (APT),
- szybkie i proste – które czasem może jednak coś popsuć (break-system-packages),
- bardziej wymagające, ale bezpieczne i uczące dobrych nawyków (środowiska wirtualne).
Na końcu będzie też o rozwiązaniu ręcznym, przez pełne obejście instalatorów – ale to bardziej w ramach ciekawostki.
Żeby uruchomić konsolę na Mincie (i wielu Linuksach), można użyć kombinacji Ctrl+Alt+T albo kliknąć odpowiednią ikonkę.
Żeby coś wkleić do konsoli, należy użyć kombinacji Ctrl+Shift+V (ew. kliknąć konsolę prawym przyciskiem myszy i wybrać opcję Wklej).
Kiedy piszę o „uruchomieniu konsoli w folderze”, to można to zrobić przez graficzną przeglądarkę plików. Po przejściu do odpowiedniego folderu należy np. kliknąć opcję Plik z górnego paska, a potem Otwórz w terminalu.
Instalacja przez APT
Niektóre popularne pakiety Pythona zostały „przepakowane” do postaci pakietów DEB. Dzięki temu można je instalować przez APT-a (systemowego menedżera pakietów). Tak jak wiele innych linuksowych programów.
W tej nowej formie udostępniane są tak popularne pakiety jak: matplotlib (wykresy), numpy (obliczenia na macierzach), pynput (automatyzacja), opencv (przetwarzanie obrazów)…
Żeby sprawdzić, czy dany pakiet jest w bazie, najlepiej najpierw odświeżyć dostępne źródła:
Jak to przy komendzie sudo – może poprosić o hasło.
Następnie można wyszukać w zasobach APT-a nazwy pakietów, przykładowo:
apt search matplotlib
Wyskoczy kilka wyników. Jak ustalić, którego z nich nam potrzeba?
Zazwyczaj nazwy pakietów mają konkretny format: python3-PAKIET, gdzie PAKIET to nazwa, pod jaką by się go instalowało w świecie Pythona.
W tym przypadku do szablonu pasuje pakiet o nazwie python3-matplotlib. Można go zainstalować:
sudo apt install python3-matplotlib
Efektem działań będzie zainstalowanie pakietu na naszym systemie. Można go od teraz importować wewnątrz różnych skryptów Pythona, a także (jeśli wspiera takie coś) wołać go przez konsolę.
Sposób dotyczy jednak tylko niektórych pakietów, które ekipa od APT-a uznała za godne publikacji. Większość modułów (jak znany torch, czyli Pytorch, od uczenia maszynowego) nie jest w taki sposób udostępnianych.
Tej metody instalacji warto użyć, gdy chcemy po prostu któregoś z najpopularniejszych pakietów Pythona.
O ile są w bazie (i odpowiadają nam ich wersje), to zainstalujemy je szybko i równie prosto jak dawniej, przez samo pip install.
Bonus: instalacja offline
Jeśli ktoś nie chce za każdym razem łączyć się z internetem, żeby pobierać moduły Pythona, to można je pobrać tylko raz, na początku, a potem nosić ze sobą jako pakiety DEB i instalować w razie potrzeby. Bez żadnego internetu.
Najpierw należy zmienić polecenie instalujące na pobierające:
apt download python3-MODUŁ
Pobierze się zestaw plików DEB (gdyby zapisało jako archiwum, to można je rozpakować i wyjąć z niego DEB-y).
Następnie, w fazie instalacji, należy skopiować te pliki do jakiegoś folderu na Linuksie, na którym chcemy je instalować, po czym użyć w tym folderze polecenia:
sudo dpkg -i python3*.deb
Efekt końcowy powinien być taki sam, jak bezpośrednia instalacja przez APT-a.
PIP z opcją break-system-packages
Długi komunikat o błędzie zawiera w dolnej części pewną propozycję, obwarowaną ostrzeżeniami:
You can override this, at the risk of breaking your Python installation or OS, by passing –break-system-packages
Passing oznacza tutaj przekazanie (argumentu). Po ludzku: jeśli dopisze się do komendy instalującej --break-system-packages, to zadziała jak dawniej.
Angielska nazwa wydaje się sugerować, że wykonanie takiego polecenia zawsze popsuje systemowe pakiety. Oczywiście to tylko straszak.
Co w końcu mógłby popsuć jednoplikowy skrypt, którego „instalacja” polega tylko na włożeniu go do folderu Pythona, żeby był dostępny dla innych?
Gdyby ktoś chciał instalować w tym trybie, to należy najpierw zainstalować PIP-a (którego domyślnie nie ma na Mincie):
apt install python3-pip
Mając PIP-a, można używać polecenia:
pip3 install PAKIET --break-system-packages
Gdybym chciał się bawić w moralizatora, to bym mówił: „nie róbcie tego! To ryzyko! Środowiska wirtualne jedyną właściwą drogą”.
…Ale wiem jak jest. Środowiska wirtualne dokładają kroków i mogą irytować, gdy chce się użyć na próbę dosłownie jednego, prostego, cudzego skryptu.
Proponuję kompromis. Używajmy tej metody wtedy, kiedy:
- modułu, który chcemy zainstalować, nie ma w bazie APT,
- do zainstalowania jest jedynie prosty moduł Pythona,
- obiecujemy sobie nie zawracać głowy twórcom naszego Linuksa, jeśli pojawią się dziwne problemy
(albo przynajmniej: przed zawaracaniem sprawdzić na czystym Linuksie z pendrive’a, czy tam również występują).
Tej metody mogą użyć osoby, które chcą pobrać lekki skrypt (np. pyperclip od obsługi schowka) z taką samą łatwością jak w dawnych czasach.
Jednocześnie upewniły się, że skrypt podczas instalacji nie grzebie w systemowym Pythonie i nie ma opcji niczego popsuć (doceniam wnikliwość).
Albo po prostu lubią ryzyko (też doceniam) ![]()
Instalacja w środowisku wirtualnym
Środowisko wirtualne Pythona (nie mylić z maszyną wirtualną, choćby taką o zastosowaniach prywatnościowych) ma dwojakie oblicze:
- od strony systemu: to odrębny folder z kopiami podstawowych programów Pythona;
-
od strony działania: to osobna przestrzeń na pliki Pythona, niewchodząca w drogę wersji systemowej.
Osobny, zamykany pokój dla dzieciaków
W to miejsce najchętniej „wypchnęliby” nas opiekunowie Linuksa, żebyśmy nie rozbili podczas zabaw wazonów z przedpokoju.
Żeby stworzyć środowisko, trzeba uruchomić konsolę w jakimś folderze (najlepiej łatwo dostępnym, bo może być często odwiedzany) i wpisać:
python3 -m venv ŚRODOWISKO
Co zrobić, jeśli po tej komendzie wyskoczy błąd
Może się zdarzyć – przynajmniej na czystym Mincie – że po użyciu cytowanego wyżej polecenia ukaże się taki komunikat:
Wynika z tego, że moduł venv (choć działa) nie ma na początku wszystkich rzeczy potrzebnych do stworzenia środowiska. Należy je sobie zainstalować:
Uwaga: przypominam, że APT to instalator dla Minta i innych systemów „debianowatych”; na innych Linuksach mógłby być inny komunikat.
ŚRODOWISKO to tutaj nazwa środowiska. Całkiem subiektywna, choć warto ustawić coś względnie krótkiego i niewywołującego ciarek żenady (nazwa domyślnie będzie widoczna w każdej linijce konsoli).
Po wykonaniu polecenia powstanie wspomniany folder ze środowiskiem wirtualnym – układ folderów i programów skopiowanych od systemowego Pythona.
Wśród tych programów jest jeden specjalny, o nazwie activate, który aktywuje całe środowisko. Można go sobie uruchomić:
source ŚRODOWISKO/bin/activate

Zobaczymy, że wygląd konsoli się zmieni – na początku linijki, w nawiasie, pojawi się nazwa naszego środowiska.
W tym trybie wszystkie pliki instalowane przez PIP-a będą trafiały do folderów środowiska, a nie do systemowych. No i, co istotne – PIP zacznie działać bez przeszkód!
Pewną wadą środowiska jest to, że trzeba sobie zapamiętać, gdzie się je stworzyło, i każdorazowo je aktywować, żeby sięgać do zebranych tam skryptów.
Wymaga to pewnej zmiany przyzwyczajeń… Ale myślę, że da się przywyknąć.
Co do sposobu stosowania – teoretycznie tym „właściwym” byłoby robienie osobnego środowiska na każdy projekt. Ale jeśli ktoś się uprze, to może po prostu stworzyć je raz, a potem wrzucić do systemowych programów wygodne skróty od jego obsługi.
W ten sposób miałoby się na systemie dwa Pythony: systemowy, którego zostawia się w spokoju, oraz własny – nasz osobisty plac zabaw.
Środowiska wirtualne to „ta właściwa” metoda, zalecana przez mędrców Pythona.
Dla osób nieprzyzwyczajonych może być z początku dziwna, bo wymaga więcej konsoli i dodatkowych krokow. Ale na dłuższą metę daje gwarancję, że świat systemowego Pythona nigdy nie zderzy się z tym bardziej chaotycznym, w którym sobie eksperymentujemy ze skryptami.
Bonus: rozwiązanie ręczne
W przypadku Pythona „instalacja” może oznaczać wiele rzeczy. Przy prostych modułach bywa po prostu umieszczeniem plików w ogólnodostępnej przestrzeni Pythona.
Weźmy taki przydatny moduł mss (skrót od Multiple ScreenShots) od robienia zrzutów ekranu. Nie ma go w bazie APT-a, dla niektórych byłby zbyt lekki na osobne środowisko wirtualne, a instalacja siłowa jednak nieco odstrasza.
Istnieje czwarty sposób – zdobycie jego kodu z pominięciem instalatorów.
Najpierw należy znaleźć moduł na stronie PyPI i przejść tam do zakładki Download files z plikami do pobrania. Pod nagłówkiem Built Distribution, na dole, znajdują się pliki WHL (w tym wypadku tylko jeden). Po kliknięciu nazwy plik pobierze się na komputer.
Gdybyśmy go spróbowali zainstalować przez PIP, to nadal wyskakiwałby błąd. Można jednak kliknąć go prawym przyciskiem myszy i rozpakować jak zwykłe archiwum ZIP (gdyby nie było widać takiej opcji, to można najpierw zmienić końcówkę pliku na .zip).
Po rozpakowaniu ukażą się dwa foldery. Jeden ma w nazwie dist-info, a drugi nazywa się po prostu mss. To on nas interesuje – jest samowystarczalnym modułem i znajdują się w nim już wszystkie pliki potrzebne do działania.
Oficjalna instalacja obejmowałaby, poza rozpakowaniem, umieszczenie tego folderu w odpowiednim miejscu. Można je znaleźć na własną rękę. W ustaleniu, gdzie Python trzyma swoje pliki, pomoże takie polecenie:
python3 -m site
Wyświetli się kilka ścieżek, jedna pod drugą. Każda z nich to dla Pythona folder szybkiego dostępu. Jeśli wrzuci się nasz folder/moduł mss do dowolnego z nich, to Python zawsze go znajdzie.
Opisałem kiedyś, w jaki sposób można stworzyć własny folder na skrypty Pythona, a następnie dodać go do listy szybkiego dostępu.
Może to być dobre rozwiązanie dla osób, które nie chcą, żeby skrypty pobierane z zewnątrz wymieszały się z ich własnymi wynalazkami.
Kiedy skopiujemy nasz folder mss do któregoś z wymienionych folderów (polecam ten kończący się na site-packages, o ile istnieje), to zyskamy możliwość importowania zawartych tam rzeczy przez systemowego Pythona:

Kolorem żółtym oznaczyłem rzeczy, które osobiście wpisałem w konsolę. Reszta tekstu – w tym ścieżka, do której wrzuciłem moduł – to rzeczy, które się wyświetliły.
Rozwiązanie ma oczywiście wiele ograniczeń. Istnieją moduły, których instalacja polega na rzeczach znacznie bardziej złożonych niż skopiowanie folderu w inne miejsce.
Nawet moduł MSS z naszego przykładu, „zainstalowany” taką metodą, nie miałby pełni funkcji. Brakowałoby skryptu-uruchamiacza, który powinien się znaleźć w systemowym folderze szybkiego dostępu (jak /usr/bin) i pozwalałby przywoływać moduł z dowolnego miejsca, krótką komendą mss.
Tym niemniej: jeśli komuś po prostu zależy na dostępie do prostego kodu, a grzęźnie na instalatorach, to warto wiedzieć, że czasem istnieje droga na skróty. Wiele sprowadza się do położenia odpowiednich plików w odpowiednich miejscach.
Na tym kończę dzisiejszy wpis. Mam nadzieję, że opisany tu błąd PIP-a uda się łatwo pokonać albo obejść którąś z kilku pokazanych tu metod ![]()