HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
zahlman
paper
Python2025–2026
zahlman / paper

paper

PAPER - the Python Application, Package and Environment wRangler

2Distinct people
12Mentions
0Explicit recommenders
3GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

PAPER - the Python Application, Package and Environment wRangler

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 5:04:57 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by month12 dated mentions

Observed mentions: 2025-02-19 11:50:05 UTC to 2026-02-08 19:50:27 UTC.

01232025-02-01 00:00:00 UTC to 2025-03-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 commentsFeb 20252025-03-01 00:00:00 UTC to 2025-04-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2025-04-01 00:00:00 UTC to 2025-05-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2025-05-01 00:00:00 UTC to 2025-06-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-06-01 00:00:00 UTC to 2025-07-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2025-07-01 00:00:00 UTC to 2025-08-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2025-08-01 00:00:00 UTC to 2025-09-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 commentsAug 20252025-09-01 00:00:00 UTC to 2025-10-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-10-01 00:00:00 UTC to 2025-11-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2025-11-01 00:00:00 UTC to 2025-12-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-12-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2026-01-01 00:00:00 UTC to 2026-02-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2026-02-01 00:00:00 UTC to 2026-03-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 commentsFeb 2026

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
Feb 20252025-02-01 00:00:00 UTC2025-03-01 00:00:00 UTC101
Mar 20252025-03-01 00:00:00 UTC2025-04-01 00:00:00 UTC000
Apr 20252025-04-01 00:00:00 UTC2025-05-01 00:00:00 UTC000
May 20252025-05-01 00:00:00 UTC2025-06-01 00:00:00 UTC101
Jun 20252025-06-01 00:00:00 UTC2025-07-01 00:00:00 UTC202
Jul 20252025-07-01 00:00:00 UTC2025-08-01 00:00:00 UTC202
Aug 20252025-08-01 00:00:00 UTC2025-09-01 00:00:00 UTC000
Sep 20252025-09-01 00:00:00 UTC2025-10-01 00:00:00 UTC101
Oct 20252025-10-01 00:00:00 UTC2025-11-01 00:00:00 UTC000
Nov 20252025-11-01 00:00:00 UTC2025-12-01 00:00:00 UTC101
Dec 20252025-12-01 00:00:00 UTC2026-01-01 00:00:00 UTC303
Jan 20262026-01-01 00:00:00 UTC2026-02-01 00:00:00 UTC000
Feb 20262026-02-01 00:00:00 UTC2026-03-01 00:00:00 UTC101

What Hacker News says

12 sources
> What are you working on? Myself, mostly. Trying to wrestle with realizing how much time I've not been spending on my supposedly main project[1] and questioning whether it's really worth doing. > Any new ideas that you're thinking about? Way too many. Writing todo lists is part of working on myself. [1]: PAPER, a pure-Python ~(pip/pipx replacement), from scratch with an emphasis on simplicity and elegance. https://github.com/zahlman/paper . There's more locally that I haven't pushed, including factoring some stuff out into a separate project and planning more of the same. But yeah.
In Ask HN: What are you working on? (February 2026)
> Do you have anything public yet? The repo is https://github.com/zahlman/paper but it's not really usable and it's missing a bunch of local very unfinished stuff (and my README template definitely needs fixing). More of a "watch this space" but I would really like to push out a Show HN for the first chunk of functionality soon.
In How uv got so fast
I guess you mean doing the things in Python that are supposedly doable from Python. Yeah, to a zeroth approximation that's my current main project (https://github.com/zahlman/paper). Of course, I'm just some rando with apparently serious issues convincing myself to put in regular unpaid work on it, but I can see in broad strokes how everything is going to work. (I'm not sure I would have thought about, for example, hard-linking files when installing them from cache, without uv existing.)
In How uv got so fast
At least in principle, I'm still working on PAPER (https://github.com/zahlman/paper). (Or I should say "resumed"; I was having a rough time of it mentally in the summer through October or so and didn't really get any actual coding done.) This has most recently involved a side diversion into a little tree-processing library (where file hierarchies are a special case) — Show HN within the next day or two, fingers crossed — and setting up a fork of https://github.com/pypa/packaging to support EOL Python (back to 3.6) and make some general simplifications (because even this is a fairly large wheel compared to the target project size). Hoping I can kick myself back into the blogging habit again soon, too.
In Ask HN: What Are You Working On? (December 2025)
> So they should be able to get similar results in Python then? I'm making PAPER (https://github.com/zahlman/paper) which is intended to prove as much, while also filling some under-served niches (and ignoring or at least postponing some legacy features to stay small and simple). Although I procrastinated on it for a while and have recently been distracted with factoring out a dependency... I don't want to give too much detail until I have a reasonable Show HN ready. But yeah, a big deal with uv is the caching it does. It can look up wheels by name and find already-unpacked data, which it hard-links into the target environment. Pip unpacks from the wheel each time (which also entails copying the data rather than doing fast filesystem operations, and its cache is an HTTP cache, which just intercepts the attempt to contact PyPI (or whatever
Read the rest
other specified index). Python offers access to hard links (on systems that support them) in the standard library. All the filesystem-related stuff is already implemented in C under the hood, and a lot of the remaining slowness of I/O is due to unavoidable system calls. Another big deal is that when uv is asked to precompile .pyc files for the installation, it uses multiple cores. The standard library also has support for this (and, of course, all of the creation of .pyc files in CPython is done at the C level); it's somewhat naive, but can still get most of the benefit. Plus, for the most part the precompiled files are also eligible for caching, and last time I checked even uv didn't do that. (I would not be at all surprised to hear that it does now!) > It totally depends on the problem that you're trying to solve. My point was more that even when you have a reasonable problem, you have to be careful about how you interface to the compiled code. It's better to avoid "crossing the boundary" any more than absolutely necessary, which often means designing an API explicitly around batch requests. And even then your users will mess it up. See: explicit iteration over Numpy/Pandas data in a Python loop, iterative `putpixel` with PIL, any number of bad ways to use OpenGL bindings....
In Performance hacks for faster Python code
(for fellow JavaScript haters: https://archive.is/Hl4yJ; but this will show collapsed accordions with important content that of course don't expand. I caved and visited the original page — but seriously, people, the <details> tag is not deep magic.) TFA documents work done for and incorporated into Pip about a year ago. Improvements like this are still worth making because, among other things, tons of people still use Pip and are not even going to look at changing. They are, I can only assume, already running massive CI jobs that dynamically grab the latest version of Pip repeatedly and stuff them into containers, in ways that defeat Pip's own caching, and forcibly check the Internet every time for new versions. Because that's the easiest, laziest thing to write in many cases. This is the only plausible explanation I have for Pip being do
Read the rest
wnloaded an average of 12 million times per day (https://pypistats.org/packages/pip). They're also worth making exactly because Pip still has a very long way to go in terms of performance improvement, and because experiments like this show that the problem is very much with Pip rather than with Python. Tons of people hyping Uv assume that it must be "rocket emoji, blazing fast, sparkle emoji" because it's written in Rust. Its performance is not in question; but the lion's share of the improvement, in my analysis, is due to other factors. Documenting past performance gains helps inform the search for future improvements. They aren't going to start over (although I am: https://github.com/zahlman/paper) so changes need to be incremental, and constantly incorporated into the existing terrible design. Showing off unexpected big-O issues is also enlightening. FTA: > This was the code to sort installed packages just before the final print. > There was a quadratic performance bug lurking in that code. The function `env.get_distribution(item)` to fetch the package version that was just installed was not constant time, it looped over all installed packages to find the requested package. The user would not expect an installation of hundreds of packages to spend a significant amount of time in preparing to state which packages were installed. But Pip has been around since 2008 (https://pypi.org/project/pip/#history) and Ian Bicking may never have imagined environments with hundreds of installed packages, never mind installing hundreds at a time. Finally, documentation like this helps highlight things that have improved in the Python packaging ecosystem, even outside of Pip. In particular: > Investigation revealed the download is done during the dependency resolution. pip can only discover dependencies after it has downloaded a package, then it can download more packages and discover more dependencies, and repeat. The download and the dependency resolution are fully intertwined. This is mostly no longer true. While of course the dependency metadata must be downloaded and cannot appear by magic, it is now available separately from the package artifact in a large fraction of cases. Specifically, there is a standard for package indices to provide that information separately (https://peps.python.org/pep-0658/), and per my discussion with Pip maintainers, PyPI does so for wheels. (Source distributions — called sdists — are still permitted to omit PKG-INFO, and dependency specifications in an sdist can still be dynamic since the system for conditional platform-dependent dependencies is apparently not adequate for everyone. But in principle, some projects could have that metadata supplied for their sdists, and nowadays it's relatively uncommon to be forced to install from source anyway.)
In Man Group – Improving Python: How we made pip install twice as fast
I agree that the built-in Python is typically not suitable for development, especially if you're planning to distribute your code and/or care about the versions of its dependencies. (And especially on Debian and its derivatives, in my experience; they even remove parts of the standard library, like Tkinter [0].) I disagree that virtual environments represent an "abyss". It takes very little effort to learn how they work [1], plus there a variety of tools that will wrap the process in various opinionated ways [2]. The environment itself is a very simple concept and requires very few moving parts; the default implementation includes some conveniences that are simply not necessary. In particular, you don't actually need to "activate" a virtual environment; in 99% of cases you can just run Python by specifying the path to the environment's Py
Read the rest
thon explicitly, and in the exceptional cases where the code is depending on environment variables being set (e.g. because it does something like `subprocess.call(['python', 'foo.py'])` to run more code in a new process, instead of checking `sys.executable` like it's supposed to, or because it explicitly checks `VIRTUAL_ENV` because it has a reason to care about activation) then you can set those environment variables yourself. Creating a virtual environment is actually very fast. The built-in `venv` standard library module actually does it faster in my testing than the equivalent `uv` command. The slow part is bootstrapping Pip from its own wheel - but you don't need to do this [2]. You just have to tell `venv` not to, using `--without-pip`, and then you can use a separate Pip (for recent versions — almost the last 3 years now) copy cross-environment using `--python` (it's a hack, but it works if you don't have to maintain EOL versions of anything). If you need heavy-duty support, there's also the third-party `virtualenv` [3]. Much of the same tooling that manages virtual environments for you — in particular, pipx and uv, and in the hopefully near future, PAPER [4] — also does one-off script runs in a temporary virtual environment, installing dependencies described in the script itself following a new ecosystem standard [5]. Uv's caching system (and of course I am following suit) makes it very fast to re-create virtual environments with common dependencies: it has caches of unpacked wheel contents, so almost all of the work is just hard-linking file trees into the new environment. [0]: https://stackoverflow.com/questions/76105218 [1]: https://chriswarrick.com/blog/2018/09/04/python-virtual-envi... [2]: https://zahlman.github.io/posts/2025/01/07/python-packaging-... [3]: https://virtualenv.pypa.io/ [4]: https://github.com/zahlman/paper [5]: https://peps.python.org/pep-0723
In I'm switching to Python and actually liking it
A lot of people like all-in-one tools, and uv offers an opinionated approach that works. It's essentially the last serious attempt at this since Poetry, except that uv is also supporting a variety of new Python packaging standards up front (most notably https://peps.python.org/pep-0621/ , which Poetry lagged on for years - see https://github.com/python-poetry/roadmap/issues/3 ) and seems committed to keeping on top of new ones. How much you can benefit depends on your use case. uv is a developer tool that also manages installations of Python itself (and maintains separate environments for which you can choose a Python version). If you're just trying to install someone else's application from PyPI - say https://pypi.org/project/pycowsay/ as an example - you'll likely have just as smooth of an experience via pipx (although installation will
Read the rest
be even slower than with pip, since it's using pip behind the scenes and adding its own steps). On the other hand, to my understanding, to use uv as a developer you'll still need to choose and install a build backend such as Flit or Hatchling, or else rely on the default Setuptools. One major reason developers are switching to uv is lockfile support. It's worth noting here that an interoperable standard for lockfiles was recently approved (https://peps.python.org/pep-0751/), uv will be moving towards it, and other tools like pip are moving towards supporting it (the current pip can write such lockfiles, and installing from them is on the roadmap: https://github.com/pypa/pip/issues/13334). If you, like me, prefer to follow the UNIX philosophy, a complete developer toolchain in 2025 looks like: * Python itself (if you want standalone binaries like the ones uv uses, you can get them directly; you can also build from source like I do; if you want to manage Python installations then https://github.com/pyenv/pyenv is solid, or you can use the multi-language https://asdf-vm.com/guide/introduction.html with https://github.com/asdf-community/asdf-python I guess) * Ability to create virtual environments (the standard library takes care of this; some niche uses are helped out by https://virtualenv.pypa.io/) * Package installer (Pip can handle this) and manager (if you really want something to "manage" packages by installing into an environment and simultaneously updating your pyproject.toml, or things like that; but just fixing the existing environment is completely viable, and installers already resolve dependencies for whatever it is they're currently installing) * Build frontend (the standard is https://build.pypa.io/en/stable/; for programmatic use, you can work with https://pyproject-hooks.readthedocs.io/en/latest/ directly) * Build backend (many options here - by design! but installers will assume Setuptools by default, since the standard requires them to, for backwards compatibility reasons) * Support for uploading packages to PyPI (the standard is https://twine.readthedocs.io/en/stable/) * Optional: typecheckers, linters, an IDE etc. A user on the other hand only needs * Some version of Python (the one provided with a typical Linux distribution will generally work just fine; Windows users should usually just install the current version, with the official installer, unless they know something they want to install isn't compatible) * Ability to create virtual environments and also install packages into them (https://pipx.pypa.io/stable/ takes care of both of these, as long as the package is an "application" with a defined entry point; I'm making https://github.com/zahlman/paper which will lift that restriction, for people who want to `import` code but not necessarily publish their own project) * Ability to actually run the installed code (pipx handles this by symlinking from a standard application path to a wrapper script inside the virtual environment; the wrappers specify the absolute path to the virtual environment's Python, which is generally all that's needed to "use" that virtual environment for the program. It also provides a wrapper to run Pip within a specific environment that it created. PAPER will offer something a bit more sophisticated here, for both aspects.)
In Fun with uv and PEP 723
They are not making a Python version. There are many competing tools in the space, depending on how you define the project requirements. Contrary to the implication of other replies, the lion's share of uv's speed advantage over Pip does not come from being written in Rust, from any of the evidence available to me. It comes from: * bootstrapping Pip into the new environment, if you make a new environment and don't know that you don't actually have to bootstrap Pip into that environment (see https://zahlman.github.io/posts/2025/01/07/python-packaging-... for some hints; my upcoming post will be more direct about it - unfortunately I've been putting it off...) * being designed up front to install cross-environment (if you want to do this with Pip, you'll eventually and with much frustration get a subtly broken installation using the old tec
Read the rest
hniques; since 22.3 you can just use the `--python` flag, but this limits you to environments where the current Pip can run, and re-launches a new Pip process taking perhaps an additional 200ms - but this is still much better than bootstrapping another copy of Pip!) * using heuristics when solving for dependencies (Pip's backtracking resolver is exhaustive, and proceeds quite stubbornly in order) * having a smarter caching strategy (it stores uncompressed wheels in its cache and does most of the "installation" by hard-linking these into the new environment; Pip goes through a proxy that uses some opaque cache files to simulate re-doing the download, then unpacks the wheel again) * not speculatively pre-loading a bunch of its own code that's unlikely to execute (Pip has large complex dependencies, like https://pypi.org/project/rich/, which it vendors without tree-shaking and ultimately imports almost all of, despite using only a tiny portion) * having faster default behaviours; e.g. uv defaults to not pre-compiling installed packages to .pyc files (since Python will do this on the first import anyway) while Pip defaults to doing so * not (necessarily) being weighed down by support for legacy behaviours (packaging worked radically differently when Pip first became publicly available) * just generally being better architected None of these changes require a change in programming language. (For example, if you use Python to make a hard link, you just use the standard library, which will then use code written in C to make a system call that was most likely also written in C.) Which is why I'm making https://github.com/zahlman/paper .
In Fun with uv and PEP 723
Ah, I misread your OP - the only part I really planned to support is "this package requires building from source, and may run arbitrary code now (not just after installation) to do so; are you sure you want to proceed?". Although the other stuff certainly seems worthwhile - I think it would be easier to plug into my design than into pip. Especially since I'm explicitly creating an internal API first and wrapping a separate CLI package around that. The project is still in quite early development stages, and not yet really usable for anything - I've been struggling to make myself sit down and implement even simple things, just personal issues. But the repository is at https://github.com/zahlman/paper and I am planning a Show HN when it seems appropriate. Hopefully the existing code at least gives an idea of the top-level design. I also desc
Read the rest
ribed it a bit in https://news.ycombinator.com/item?id=43825508 . I've also written a few posts on my blog (https://zahlman.github.io) about design problems with pip, and going forward I'll be continuing that, along with giving a basic overview of the PAPER design and explaining how it addresses the problems I've identified.
In Show HN: Pipask – safer pip without compromising convenience
> The idea of a new environment for each of my related “projects” just doesn’t make sense to me. But, I’m open to learning a new workflow. First, let me try to make sense of it for you - One of uv's big ideas is that it has a much better approach to caching downloaded packages, which lets it create those environments much more quickly. (I guess things like "written in Rust", parallelism etc. help, but as far as I can tell most of the work is stuff like hard-linking files, so it's still limited by system calls.) It also hard-links duplicates, so that you aren't wasting tons of space by having multiple environments with common dependencies. A big part of the point of making separate environments is that you can track what each project is dependent on separately. In combination with Python ecosystem standards (like `pyproject.toml`, the inli
Read the rest
ne script metadata described by https://peps.python.org/pep-0723/, the upcoming lock file standard in https://peps.python.org/pep-0751/, etc.) you become able to reproduce a minimal environment, automate that reproduction, and create an installable sharable package for the code (a "wheel", generally) which you can publish on PyPI - allowing others to install the code into an environment which is automatically updated to have the needed dependencies. Of course, none of this is new with `uv`, nor depends on it. The installer and venv management tool I'm developing (https://github.com/zahlman/paper) is intended to address use cases like yours more directly. It isn't a workflow tool, but it's intended to make it easier to set up new venvs, install packages into venvs (and say which venv to install it into) and then you can just activate the venv you want normally. (I'm thinking of having it maintain a mapping of symbolic names for the venvs it creates, and a command to look them up - so you could do things like "source `paper env-path foo`/bin/activate", or maybe put a thin wrapper around that. But I want to try very hard to avoid creating the impression of implementing any kind of integrated development tool - it's an integrated user tool, for setting up applications and libraries.)
In A year of uv: pros, cons, and should you migrate

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.