2 Punkte von GN⁺ 5 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • uv punktet mit hoher Geschwindigkeit, Python-Versionsverwaltung und der Integration in ein einziges Binary, aber die UX der Paketverwaltung in der Wartungsphase wirkt noch grob
  • Veraltete Pakete lassen sich mit uv pip list --outdated prüfen, doch da der Befehl kein Top-Level-Kommando ist, sondern unter dem pip-kompatiblen Namespace liegt, ist er schwerer zu entdecken
  • uv add pydantic fügt standardmäßig eine offene Versionsbeschränkung nach oben wie pydantic>=2.13.4 hinzu und erlaubt damit sogar Sprünge auf neue Major-Versionen
  • Vollständige Upgrades erfolgen über uv lock --upgrade, und für mehrere einzelne Pakete muss --upgrade-package wiederholt werden, was den Befehl unnötig lang macht
  • Mit der Einstellung add-bounds = "major" lassen sich sicherere Standardbeschränkungen setzen, aber die Funktion ist noch im Preview-Status, und für Anwendungen wird eine intuitivere Update-UX benötigt

Die Stärken von uv und die Unbequemlichkeit in der Wartungsphase

  • uv von Astral überzeugt durch hohe Geschwindigkeit, Python-Versionsverwaltung und dadurch, dass es mehrere Werkzeuge durch ein einziges Binary ersetzt
  • Der Einstieg in ein neues Python-Projekt und das Hinzufügen der ersten Abhängigkeit ist einfach, aber sobald ein Projekt in die Wartungsphase kommt, wirkt die UX für das Prüfen veralteter Pakete und regelmäßige Upgrades rauer als bei pnpm oder Poetry
  • Die zentralen Probleme sind die Auffindbarkeit des Befehls zum Prüfen veralteter Pakete, das Fehlen einer oberen Standardgrenze bei Versionsbeschränkungen und die Umständlichkeit der Upgrade-Befehle

Veraltete Pakete prüfen

  • In JavaScript-Projekten zeigt pnpm outdated veraltete Pakete, aktuelle Versionen, neueste Versionen und die laut Constraints erlaubten Versionen kompakt an
  • In uv gibt es kein Top-Level-Kommando uv outdated; anfangs wurde stattdessen folgender Befehl verwendet
$ uv tree --outdated --depth 1
  • uv tree --outdated --depth 1 filtert nicht nur die veralteten Einträge heraus, sondern gibt den gesamten Top-Level-Abhängigkeitsbaum aus und versieht aktualisierbare Einträge nur mit einem kleinen Hinweis
  • Wenn es 50 Abhängigkeiten gibt und nur 2 Pakete veraltet sind, muss man trotzdem eine Liste mit 50 Zeilen durchsuchen
  • Auch poetry show --outdated ist vom Namen her weniger intuitiv, zeigt in der Ausgabe aber tatsächlich nur die veralteten Pakete

Das Risiko der Standard-Versionsbeschränkungen

  • Der Standardansatz von pnpm und Poetry

    • pnpm add schreibt eine Caret-Anforderung wie ^1.23.4 in die package.json
    • ^1.23.4 erlaubt Versionen aus dem Bereich 1.x.x, aktualisiert aber nicht auf 2.0.0
    • Poetry verwendet standardmäßig ebenfalls ein Format wie >=1.23.4,<2.0.0; es ist weniger gut lesbar, hat aber denselben Effekt
    • Bei beiden Tools lässt sich unter der Annahme, dass ein Paket SemVer befolgt, mit pnpm update oder poetry update die Wahrscheinlichkeit verringern, dass ein Build durch größere API-Änderungen bricht
  • Der Standardansatz von uv

    • uv add pydantic fügt in pyproject.toml standardmäßig eine Beschränkung ohne obere Grenze wie die folgende ein
dependencies = [
    "pydantic>=2.13.4",
]
  • Mit dieser Beschränkung sind pydantic-Versionen 2, 3 oder 100 gleichermaßen zulässig
  • Wer ein Massenupdate ausführt, übernimmt damit nicht nur Bugfixes, sondern auch inkompatible Änderungen, die Maintainer im gesamten Abhängigkeitsgraphen veröffentlicht haben
  • Gerade bei der Wartung von Anwendungen kann das zu Stabilitätsrisiken führen

Die UX der Upgrade-Befehle

  • Bei pnpm und Poetry ist ein vollständiges Update jeweils so einfach
$ pnpm update
$ poetry update
  • In uv wird für ein vollständiges Upgrade folgender Befehl verwendet
$ uv lock --upgrade
  • uv lock --upgrade funktioniert nicht als uv update oder uv upgrade, sondern als Option des lock-Befehls und wirkt daher für Menschen als Paketverwaltungsbefehl weniger intuitiv
  • In Kombination mit offenen Versionsbeschränkungen nach oben bedeutet uv lock --upgrade, alle Pakete in der Lockfile auf die absolut neuesten Versionen anzuheben
  • Dazu können auch tief verschachtelte Abhängigkeiten gehören, die man gar nicht direkt kennt
  • Wenn nur bestimmte Pakete aktualisiert werden sollen, kann man bei pnpm die Paketnamen einfach so auflisten
$ pnpm update pydantic httpx uvicorn
  • In uv muss für jedes Paket das Flag --upgrade-package wiederholt werden
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
  • Wenn mehrere Pakete auf einmal aktualisiert werden sollen, wird das wiederholte Flag schnell zu einer spürbaren Unannehmlichkeit

Das Flag --bounds und die Konfiguration

  • Für uv add wurde kürzlich die Option --bounds hinzugefügt
$ uv add pydantic --bounds major
  • Dieser Befehl erzeugt die sicherere Beschränkung pydantic>=2.13.4,<3.0.0
  • --bounds major ist derzeit eine Preview-Funktion und muss pro Befehl explizit aktiviert werden
  • Später stellte sich heraus, dass sich in pyproject.toml ein Standardwert einmalig setzen lässt
[tool.uv]
add-bounds = "major"
  • Mit dieser Einstellung erhält uv add künftig vernünftigere Standardwerte, ohne dass jedes Mal --bounds major angegeben werden muss
  • Für Anwendungen wäre es besser, wenn dieses Verhalten Standard wäre, aber die tatsächliche Nutzbarkeit ist nicht ganz so schlecht, wie zunächst dargestellt

Der Unterschied zwischen Anwendungen und Bibliotheken

  • Der Standardrat im Python-Packaging lautet, dass Bibliotheken, die auf PyPI veröffentlicht werden, keine obere Versionsgrenze festschreiben sollten; dieser Rat ist sinnvoll
  • Würden alle Bibliotheken obere Grenzen fixieren, könnte der Abhängigkeitsbaum nachgelagerter Nutzer unter Umständen nicht mehr auflösbar sein
  • Anwendungen hingegen sind das Endstück des Abhängigkeitsgraphen, und andere Nutzer lösen ihre Abhängigkeiten nicht anhand dieser Constraints auf
  • Bei Anwendungen gibt es keinen Nachteil durch obere Grenzen, dafür aber Schutz vor unerwarteten Sprüngen auf neue Major-Versionen
  • Der hier gemeinte Kontext ist die Wartung von Anwendungen wie Websites, Services oder internen Tools; für die Veröffentlichung von Bibliotheken kann ein Standard ohne obere Grenze sinnvoll sein

Korrigierte Punkte und verbleibende Probleme

  • Mit uv pip list --outdated lassen sich tatsächlich nur die veralteten Pakete gefiltert anzeigen
$ uv pip list --outdated
  • Dadurch wird die Kritik an der lauten Ausgabe von uv tree --outdated --depth 1 abgeschwächt
  • Das verbleibende Problem ist, dass diese Funktion nicht als Top-Level-Kommando, sondern unter dem pip-kompatiblen Namespace liegt und daher schwer zu entdecken ist
  • Mit add-bounds = "major" lässt sich ein Standard für Bounds festlegen, sodass die Gegenüberstellung „entweder jedes Mal manuell anpassen oder das Risiko akzeptieren“ so nicht ganz stimmt
  • Trotzdem ist die Funktion noch im Preview-Status, und für die Paketverwaltung in Anwendungen braucht es sicherere Standard-Constraints und intuitivere Update-Befehle

Gewünschte Verbesserungen

  • Es braucht ein eigenes Kommando uv outdated, das klar nur veraltete Pakete anzeigt
  • Es braucht einen ergonomischeren update-Befehl, bei dem für mehrere Pakete keine Flags wiederholt werden müssen
  • Standardmäßige Versionsbeschränkungen sollten die Stabilitätserwartungen semantischer Versionsverwaltung (SemVer) besser widerspiegeln
  • Im aktuellen Zustand bleibt die Last bestehen, jede einzelne Zeile einer Lockfile-Änderung misstrauisch prüfen zu müssen

1 Kommentare

 
GN⁺ 5 시간 전
Hacker-News-Kommentare
  • Der Standard-Versionsbereich von uv add kann als dauerhafte Einstellung festgelegt werden, sodass man ihn nicht jedes Mal mitgeben muss.
    Siehe: https://docs.astral.sh/uv/reference/settings/#add-bounds
    Der Grund, warum standardmäßig keine Obergrenze gesetzt wird, ist, dass das im Ökosystem viele unnötige Konflikte erzeugt. Aus meiner Poetry-Zeit habe ich dazu auch einmal Material gesammelt: https://github.com/zanieb/poetry-relax#references

    • Ich verstehe, dass es beim Veröffentlichen von Bibliotheken wichtig ist, Versionsobergrenzen zu entfernen, aber der Artikel ist aus der Perspektive geschrieben, eine Website zu bauen, nicht eine Bibliothek.
      Wenn ich in einem Webprojekt Abhängigkeiten nutze, möchte ich Obergrenzen haben, um Breaking Changes zu vermeiden — unter der Annahme, dass die Abhängigkeiten SemVer einhalten.
    • Auch die Haskell-Community hat viele Jahre mit diesem Problem gerungen, und der zeitweise erfolgreichste Ansatz war Stackage.
      Dort wurde davon abgeraten, defensive Obergrenzen zu setzen, und stattdessen wurde bei jedem Release ein großer, aktiver Teil des Ökosystems fortlaufend gebaut, um echte Kompatibilitätsprobleme zu finden; die Eigentümer wurden automatisch benachrichtigt, und es gab einen klaren Zeitplan, um im nächsten „LTS“-Release zu bleiben.
      Inzwischen scheint schon der Cabal-Solver ziemlich stabil zu sein, aber breite Nightly-Builds sowie sichtbare Fehler und Blocker dürften geholfen haben, das Ökosystem weiter auflösbar zu halten.
    • Ich habe erst jetzt von der Einstellung add-bounds erfahren. Exaktes Pinning von Abhängigkeiten ist zwar wichtig, aber gerade für weniger erfahrene Entwickler ist das nützlich bei Projekten, die man leicht falsch aufsetzt — insbesondere bei Endprodukten statt Bibliotheken.
    • Ich frage mich, ob es eine Möglichkeit gibt, das Flag --native-tls dauerhaft zu setzen.
      Wegen der Zscaler-Konfiguration bei uns im Unternehmen schlägt UV ohne dieses Flag immer fehl.
      Mich würde auch interessieren, ob geplant ist, eine Funktion zu unterstützen, mit der man eine kompatible Python-Version für eine bestimmte Architektur festlegen kann. Eines der Pakete, die wir intern pflegen, braucht 32-Bit-Python, daher muss ich immer --python /path/to/32bit mitgeben.
    • Vielleicht ist das eine etwas unausgereifte Frage, aber ich frage mich, ob es eine Möglichkeit gibt, uv dazu zu bringen, exclude-newer aus pyproject.toml zu respektieren.
      Wenn ich uv run ausführe, wird exclude-newer aus pyproject.toml entfernt.
      Ich könnte zwar jedes Mal uv run —-frozen oder uv run --exclude-newer ausführen, aber das wirkt nicht wie der richtige Workflow; vielleicht übersehe ich einen idiomatischen Weg.
  • Dass uv keine Obergrenzen setzt, ist Absicht, weil es ein einzelnes Resolver-Ergebnis braucht.
    npm kann in verschiedenen Teilen des Baums unterschiedliche Resolver-Ergebnisse installieren, aber in Python ist das keine Option. In Rye mussten wir dieselbe Entscheidung treffen, und dafür gibt es keine bessere Lösung.
    Wenn man Obergrenzen setzt, kann das in der Praxis zu Bäumen führen, die sich gar nicht mehr auflösen lassen. Teile des Python-Paketökosystems haben früher sogar Overrides für alte Pakete ausgeliefert, die mit falsch angenommenen Obergrenzen veröffentlicht worden waren.
    Zum heutigen Zeitpunkt kann man nicht wissen, ob ein noch nicht veröffentlichtes Paket mit dem eigenen Paket kompatibel sein wird oder nicht.

    • Persönlich finde ich es besser, beim Aktualisieren von uv eine Fehlermeldung zu bekommen, dass Pakete nicht kompatibel sind, und dann bei Bedarf zu overriden.
      Das ist besser, als zur Laufzeit auf schwer nachvollziehbare Versionsinkompatibilitäten zu stoßen.
    • Dass in pyproject.toml keine Obergrenzen stehen, ist nicht das eigentliche Problem.
      Das eigentliche Problem ist, dass uv lock —-upgrade alles ohne Obergrenze pauschal aktualisiert.
      Wenn es eine Möglichkeit gäbe, Pakete zu aktualisieren, ohne Major-Versionen anzuheben, wäre dieser Befehl deutlich sicherer.
    • uv hat vieles verbessert, aber es scheint grundsätzlich einiges zu geben, das sich nicht allein auf Tool-Ebene lösen lässt.
      Im Vergleich zur Zeit vor uv ist es viel besser geworden, aber ganz gut wird es wohl schwer, ohne dass das ganze Ökosystem in gewissem Maß Breaking Changes macht. Wenn man an den Übergang von Python 2 auf 3 denkt, dürfte der Wunsch nach solchen Änderungen auf absehbare Zeit auch nicht besonders groß sein.
    • Für Bibliotheksautoren stimmt das, aber wenn ich eine Website baue und von vielen Paketen abhänge, möchte ich Obergrenzen, damit Upgrades sicher bleiben.
      Das Flag —-bound hilft, aber es ist wieder etwas, das man eintippen und im Kopf behalten muss.
      Wenn uv erkennen kann, dass das betreffende Projekt keine Bibliothek ist, könnte es dann nicht standardmäßig Obergrenzen setzen?
    • Eigentlich ist die richtige Nutzung — egal ob uv oder npm —, alles auf = umzustellen, nicht darauf zu vertrauen, dass nicht-major Updates nicht kaputtgehen, und nur manuell zu aktualisieren.
  • In einer laufenden App habe ich 257 Python-Abhängigkeiten, mehr als die Hälfte davon direkte Abhängigkeiten.
    In pyproject.toml setze ich keine Obergrenzen, und alle zwei Wochen lasse ich per GitHub Actions uv lock --upgrade laufen.
    Die Testabdeckung ist gut, daher schlagen bei Problemen die Tests fehl, und wir haben zusätzlich einen KI-gestützten Review-Workflow. Wenn ein Upgrade-PR erstellt wird, listet ein KI-Workflow per Python-Skript Major- und Minor-Versionsupdates auf, sucht Changelogs, verlinkt und fasst sie zusammen und analysiert für jedes Paket das Risiko auf Basis der Nutzung im Codebestand.
    Insgesamt ist das fast schmerzfrei, und ich muss Pakete weder einzeln anheben noch alte Pakete prüfen oder verwaiste Abhängigkeiten aufräumen. Fälle, in denen Fixes durch die Abhängigkeitsautoren nötig sind und sich das nicht im Code lösen lässt, sind sehr selten — ungefähr einmal pro Jahr. In den letzten drei Monaten gab es 18 Major-Versionserhöhungen, und nur eine davon erforderte Codeänderungen.
    Im Frontend würde ich das auch gern so machen, aber dort sind die Tests nicht gut genug, um es sicher laufen zu lassen. Backend-Tests sind leichter zu schreiben und wichtiger, deshalb finde ich, dass jeder Codebestand sie haben sollte. Mit Tests kann man einfach alles automatisch aktualisieren.

    • Tests zu schreiben ist auch etwas, worin KI-Agenten gut sind.
      Zumindest darin, natürlichsprachliche Anweisungen in präzise Tests zu übersetzen, sind sie hervorragend.
      Ich habe seit einiger Zeit keine Tests mehr von Hand geschrieben; früher habe ich mich immer darüber beschwert, heute nicht mehr.
  • UV hat viel für Python getan, aber ich habe heute ziemlich damit gerungen.
    Ich wollte Skripte zentral verwalten, die über mehrere Repositories verteilt sind und sich im Lauf der Zeit unterschiedlich entwickelt haben.
    Die Idee war uv run --with $package main --help, und automatisch sollte 1) bei Bedarf installiert und dann ausgeführt werden, 2) nichts installiert werden, wenn bereits aktuell, und 3) andernfalls ein Update erfolgen.
    Aber alle drei Punkte waren schwieriger als erwartet. Im Grunde hat uv run jedes Mal neu installiert, und virtuelle Umgebung plus Installation haben 6 Sekunden gedauert.
    uvx oder uv tool waren auch nicht viel besser, weil dann ein neues Problem entstand: Die Nutzer bekamen keine Upgrades mehr.
    Am Ende habe ich ein Skript gebaut, das einen paginierten GET gegen CodeArtifact schickt, bei einer neueren Nicht-Development-Version aktualisiert und dann neu startet. Das funktioniert, und 200 ms Latenz sind besser als 6 Sekunden, aber es war nicht die gewünschte Erfahrung.

    • uv run --with $package main --help sollte genau dieses Verhalten mit sehr wenig Overhead liefern, daher bin ich etwas verwirrt.
      Es sollte nicht jedes Mal neu installieren; --with-Umgebungen werden im Cache gespeichert und wiederverwendet. Selbst wenn die Umgebung nicht gecacht wäre, würden die Abhängigkeiten gecacht, und eine Installation aus dem Cache ist sehr schnell. Das sollte definitiv unter 200 ms liegen.
      Wenn du ein reproduzierbares Beispiel ausführlich aufmachst, schaue ich es mir gern an.
    • Für diesen Anwendungsfall wirken uv tool install und uv tool upgrade passend.
      Solche kleinen Reibungspunkte scheinen sich aber relativ leicht beheben zu lassen; es wäre gut, wenn du dazu ein Issue eröffnest.
    • Du kannst die nötigen Abhängigkeiten auch in einem Dokumentationsblock am Anfang der Datei definieren und dann einfach uv run main ausführen.
      Dann werden die erforderlichen Abhängigkeiten automatisch installiert, gecacht und ausgeführt: https://docs.astral.sh/uv/guides/scripts/
    • Vielleicht sollten die Nutzer einfach uv tool upgrade ausführen.
    • https://copier.readthedocs.io/en/stable/ ist ebenfalls einen Blick wert.
      Ich weiß nicht, ob das exakt derselbe Anwendungsfall ist, aber zum Synchronisieren eines Polyrepo-Microservice-Ökosystems war es sehr gut.
  • Ich fand es ziemlich überraschend, dass "uv tree --outdated --depth 1" empfohlen wurde, um eine Liste veralteter Abhängigkeiten zu sehen.
    Ich persönlich nutze seit der Einführung "uv pip list --outdated".
    Ich stimme aber zu, dass ein so wichtiger Befehl ein eigenes Top-Level-Subkommando verdient hätte.

    • Aus Sicht des Autors war das weniger eine Empfehlung als die einzige bekannte Methode.
      "uv pip list --outdated" liefert definitiv die viel bessere Ausgabe, danke dafür.
      Aber dass es überhaupt zwei Wege gibt, veraltete Pakete anzuzeigen, und dass die Ausgabe so stark abweicht, lässt die UX für mich gerade deshalb chaotisch wirken.
    • "uv tree -od1" sollte vermutlich auch funktionieren.
      Ein Teil der Kritik an Paketmanagern wie pacman war aber auch, dass man für häufige Befehle — wie bei apt — menschenfreundliche Kommandos anbieten sollte.
  • Gemessen am Wort „chaotisch“ im Titel bestehen die Beispiele eher daraus, ein paar zusätzliche Argumente tippen zu müssen.
    Ein besserer Titel wäre vielleicht Quality-of-Life-Verbesserungen, die ich mir für UV wünsche.

    • Diese Formulierung und Sätze wie „Wer hat dieses Command-Line-Interface entworfen?“ wirken auf mich wie Mittel, um Aufmerksamkeit und Klicks zu erzeugen.
      Das Feedback selbst ist nützlich, und ich stimme dem meiste davon zu, aber solche Formulierungen mindern den Wert des Feedbacks und rufen defensive Reaktionen hervor.
      Ich finde die Command-Line-Schnittstelle von uv persönlich ebenfalls umständlich, aber ich verstehe, warum sie so geschrieben wurde.
  • uv ist großartig, aber das aktuell größte Problem im Python-Packaging ist weiterhin, wissenschaftliches/Machine-Learning-Packaging vernünftig zu handhaben.
    Wenn man PyTorch installieren will, muss man zuerst klären, welche Version und ob CUDA. Falls CUDA, gibt es gleich 6 Varianten je nach CUDA-Version, und die Wheels sind außerdem zu groß für PyPI, also muss man sie direkt herunterladen.
    Conda löst dieses Problem nur teilweise. Spack ist extrem konfigurierbar und eignet sich hervorragend, um die nötigen C/C++/Fortran-Abhängigkeiten und Compiler-Toolchains für maximale Performance bereitzustellen, integriert sich aber nicht gut mit uv und Ähnlichem. Deshalb ist es schwer, experimentelle Machine-Learning-Projekte aus der Forschung bis in die Produktion zu bringen.

    • Früher bin ich über Anaconda ausgewichen, aber da kommt so viel Kram mit, und die Entwicklungsumgebung unterscheidet sich dann völlig von der Produktionsumgebung — das war auch nicht ideal.
      Am Ende landet man wieder in der eingangs beschriebenen Situation.
  • Da steckt viel nützliches Feedback drin, aber auch klickbaitartige Formulierungen.
    Was pnpm outdated betrifft: Das kam bisher nicht besonders oft auf, wirkt aber wie eine vernünftige Anforderung. Es scheint aus den unterschiedlichen Kulturen von Python und JavaScript zu kommen. Ich habe mich bei Python-Abhängigkeiten fast nie dafür interessiert, ob sie veraltet sind, solange sie nicht unsicher oder kaputt sind; im JavaScript-Ökosystem scheint es dagegen ziemlich üblich zu sein, bei Gelegenheit Upgrades mitzunehmen. Das heißt nicht, dass das schlecht ist — es zeigt nur, wie unterschiedlich die Intuition darüber sein kann, was ein Command-Line-Interface zwischen großen Programmiersprachen-Communities sichtbar machen sollte.
    Wie Armin sagte, ist das Verhalten von uv bei Obergrenzen beabsichtigt und aufgrund der Python-Resolver-Strategie funktional notwendig. Das ist ein Trade-off, den Python im Vergleich zu anderen Sprachen eingegangen ist, aber ich halte ihn für einen guten Trade-off, weil es im Abhängigkeitsbaum nur je eine Version pro Abhängigkeit gibt und alle verflochtenen Anforderungen darauf aufgelöst werden.
    Dass uv lock --upgrade so funktioniert, liegt daran, dass es nicht die Anforderungen des Nutzers, sondern die Lock-Datei aktualisiert. pnpm update hingegen scheint die Nutzeranforderungen in package.json zu aktualisieren. Das kann verwirrend sein, aber unter uv lock ist es präziser eingeordnet. Andernfalls gäbe es Nutzer, die verwirrt wären, warum uv upgrade nicht das Update ausführt, das sie jeweils erwarten. Trotzdem gibt es noch Spielraum, das sauberer sichtbar zu machen, und offenbar besteht klare Nachfrage nach einem uv-Subkommando, das auch die Anforderungen selbst direkt aktualisiert.
    https://news.ycombinator.com/item?id=48230048

    • Bei veralteten Paketen und Obergrenzen stimme ich zu, aber wenn Nutzer sich darüber beschweren, dass die Oberfläche schwierig ist, steckt definitiv etwas dahinter.
      Dass der Befehl uv lock nur die Lock-Datei betrifft, ist sinnvoll, aber Nutzer haben reale Anforderungen, direkte und transitive Abhängigkeiten zu aktualisieren. Für transitive Abhängigkeiten geht das mit uv lock --upgrade-package, aber das ist etwas umständlich. Es funktioniert auch für direkte Abhängigkeiten, berührt aber pyproject.toml nicht — und genau diese Datei springt Entwicklern viel stärker ins Auge.
      Wenn die Paketversionen in uv.lock pyproject.toml vorauslaufen, ist pyproject.toml als Wegweiser für die Oberfläche der Abhängigkeiten weniger verlässlich. Ein benutzerfreundlicher uv upgrade-Befehl wäre schön.
      Die bislang größte UX-Falle bei uv ist für mich uv pip. Viele Projekte nutzen uv in der Entwicklung korrekt mit pyproject.toml und uv.lock, umgehen aber in Deployment-Dockerfiles oder CI-Tools die uv.lock, indem sie uv pip install -r pyproject.toml verwenden.
      Es ist zwar ein Problem, dass Coding-Agenten wegen der vielen pip-Beispiele in Trainingsdaten schlechte uv pip-Muster empfehlen, aber uv sollte auch Schutzmechanismen bieten, die Nutzer davor bewahren.
      uv ist ein großartiges Tool und sollte aus meiner Sicht noch viel breiter eingesetzt werden: https://aleyan.com/blog/2026-why-arent-we-uv-yet
    • Wenn das aus Sicht des Autors „klickbaitartig“ wirkte, tut es ihm leid, aber tatsächlich sei es einfach niederländische Direktheit und Ehrlichkeit.
      poetry update aktualisiert ebenfalls die Lock-Datei. Ich finde die Struktur der uv-CLI ziemlich mühsam im Alltag. Sie wirkt für Korrektheit und Maschinen entworfen, nicht für Benutzerfreundlichkeit.
    • Für mich als jemand, der von pip zu uv gewechselt ist, heißt das: Wenn ich diese Information brauche, lande ich wieder bei uv pip list --outdated.
    • uv upgrade steht auf der Roadmap.
      Dass es noch nicht da ist, liegt daran, dass sich nur schwer eine wirklich gute Experience bauen lässt, viel mehr Nuancen darin stecken, als die Leute erwarten, und das Team klein ist und viele Prioritäten hat.
    • Ein Einsatzzweck von Funktionen im Stil von pnpm outdated ist zu sehen, was aktualisiert wird, wenn man "uv sync --update" oder "uv lock --update" ausführt.
      Vielleicht wäre es aber sogar besser, bei diesen Befehlen einen Bestätigungs-Prompt einzubauen.
  • Pixi nutzt uv als Backend, und mir gefiel die UI, weil man sehr einfach Task-Aliase ergänzen kann, die veraltete Pakete hübsch auflisten.
    Besonders Pixi-diff-to-markdown macht es leicht, automatische CI-Paketupdates schnell zu überblicken.
    Wenn du unter den veralteten Paketen sehen willst, was aktualisiert würde, kannst du im Projekt einen solchen Task-Alias anlegen:
    pixi task add outdated "pixi update --dry-run --json | pixi exec pixi-diff-to-markdown"
    Danach einfach im Projekt pixi run outdated ausführen.
    Die Ausgabe ist eine gut lesbare Markdown-Tabelle mit den Paketen, die aktualisiert würden, ihrer bisherigen Version und der neuen Version, die der Befehl pixi update installieren würde. Natürlich hängt das auch von Geschmack und Situation ab.

  • Vor Kurzem tauchte ein env-Skript im Pfad auf und störte die Nutzung des normalen UNIX-Befehls env.
    Wie sich herausstellte, legt der uv-Installer das an, wenn man folgenden Befehl ausführt:
    curl -LsSf [https://astral.sh/uv/install.sh](<https://astral.sh/uv/install.sh>;) | sh
    Installiert wird nach $HOME/.cargo/bin/, und es wird ein Shell-Skript unter $HOME/.cargo/env erstellt, das $HOME/.cargo/bin/ an den Anfang von PATH setzt, falls es noch nicht enthalten ist.
    Es ist schwer nachzuvollziehen, was für Programmierer Code schreiben, der auf diese Weise grundlegende UNIX-Befehle überschreibt.