Hacker Newsnew | past | comments | ask | show | jobs | submit | networked's commentslogin

Inline script metadata itself is not tied to uv because it's a Python standard. I think the association between the two comes from people discovering ISM through uv and from their simultaneous rise.

pipx can run Python scripts with inline script metadata. pipx is implemented in Python and packaged by Linux distributions, Free/Net/OpenBSD, Homebrew, MacPorts, and Scoop (Windows): https://repology.org/project/pipx/versions.


Yes, many things can use inline script metadata.

But a script only has one shebang.


Perhaps a case for standardizing on an executable name like `python-script-runner` that will invoke uv, pipx, etc. as available and preferred by the user. Scripts with inline metadata can put it in the shebang line.

I see it has been proposed: https://discuss.python.org/t/standardized-shebang-for-pep-72....


I get the impression that others didn't really understand your / the OP's idea there. You mean that the user should locally configure the machine to ensure that the standardized name points at something that can solve the problem, and then accepts the quirks of that choice, yes?

A lot of people seem to describe a PEP 723 use case where the recipient maybe doesn't even know what Python is (or how to check for a compatible version), but could be instructed to install uv and then copy and run the script. This idea would definitely add friction to that use case. But I think in those cases you really want to package a standalone (using PyInstaller, pex, Briefcase or any of countless other options) anyway.


> You mean that the user should locally configure the machine to ensure that the standardized name points at something that can solve the problem, and then accepts the quirks of that choice, yes?

I was thinking that until I read the forum thread and Stephen Rosen's comments. Now I'm thinking the most useful meta-runner would just try popular runners in order.

I have put up a prototype at https://github.com/dbohdan/python-script-runner.


Neat. Of course it doesn't have much value unless it's accepted as a standard and ships with Python ;) But I agree with your reasoning. Might be worth reviving that thread to talk about it.

You can use https://github.com/erning/gorun as a Go script runner. It lets you embed `go.mod` and `go.sum` and have dependencies in Go scripts. This is more verbose than Python's inline script metadata and requires manual management of checksums. gorun caches built binaries, so scripts start quickly after the first time.

Example:

  #! /usr/bin/env gorun
  //
  // go.mod >>>
  // module foo
  // go 1.22
  // require github.com/fatih/color v1.16.0
  // require github.com/mattn/go-colorable v0.1.13
  // require github.com/mattn/go-isatty v0.0.20
  // require golang.org/x/sys v0.14.0
  // <<< go.mod
  //
  // go.sum >>>
  // github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
  // github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
  // github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
  // github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
  // github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
  // github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
  // github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
  // golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
  // golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
  // golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
  // golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
  // <<< go.sum

  package main

  import "github.com/fatih/color"

  func main() {
      color.Green("Hello, world!")
  }
The shebang line can be replaced for compatibility with standard Go tooling:

  /// 2>/dev/null ; gorun "$0" "$@" ; exit $?
  //
  // go.mod >>>
  // ...

I was looking for something like this a few times! great

> Adding static typing to a dynamic language mostly gives you the disadvantages of both, without a lot of benefits.

Can you elaborate? I don't share this experience, and I'm interested in bringing static typing to a language without static typing, so I'd like to understand. In new Python and JavaScript codebases, optional typing has had clear benefits for refactoring and correctness and low costs for me. Legacy codebases can be different.


I don't have a great code example at hand unfortunately, but I found that people often tend to write more "nominally" typed code (expecting explicitly named classes) rather than taking advantage of duck typing (interfaces, structural types), meaning the code becomes more rigid, harder to change and more time wasted on resolving all the type checks, even if the code otherwise is perfectly reasonable and free of bugs.

In other words, I found that the resulting code often looked more like Java but with weaker guarantees about types and much worse performance.


Part of it is because Ruby imo, have a very nice syntax. With type annotation, it's becoming "ugly", a lot more verbose. It's no longer English-like. I do agree type have some advantages, but we need to get the DX right.

I've been using Ruby for more than 10 years now, and I only started using LSP recently. To me it's a nice addition but I can live without it. Type is just one of the tools, not the only one imo. Not trying to sound negative but type is becoming more like a hammer analogy nowadays.

And it's not limited to Ruby. Javascript, Python, all similar languages. Not everyone is a fan of type. We won't reach consensus imo and that's ok.


> With type annotation, it's becoming "ugly", a lot more verbose. It's no longer English-like.

In our codebase that uses Sorbet I find this is really only true at function boundaries. Within a function it is pretty rare that anything needs to be spelled out with inline annotations to satisfy the compiler.


This is my biggest irk about Sorbet: because its signatures are wordy and because it can't infer the generic type of a private method, it slightly pushes you towards NOT extracting helper methods if they are going to be 2-5 lines. With Sorbet annotation, it'd easily become 10 lines. So it pushes towards bigger methods, and those are not always readable.

If only private methods would be allowed not having typing at all (with a promise of not being used in subclasses, for example), and Sorbet would be used mostly on the public surface of classes, it'd be much more tolerable for me.


Previously:

- Perl's decline was cultural - https://news.ycombinator.com/item?id=46175112 - Dec 2025 (460 comments)

- (!) Ask HN: Why did Python win? - https://news.ycombinator.com/item?id=37308747 - Aug 2023 (839 comments)

- Ask HN: Why is Python so popular for ML/DS? - https://news.ycombinator.com/item?id=16207834 - Jan 2018 (19 comments)

- Ask HN: Is Python dying? - https://news.ycombinator.com/item?id=11100251 - Feb 2016 (352 comments)

- Python is now the most popular introductory language at top U.S. universities - https://news.ycombinator.com/item?id=8001337 - July 2014 (362 comments)

- Ask HN: Why Python over Ruby? - https://news.ycombinator.com/item?id=682101 - July 2009 (196 comments)

- Ask HN: What does Ruby have that Python doesn't? - https://news.ycombinator.com/item?id=283639 - Aug 2008 (223 comments)


Even with daemon(8), PID files and the lack of process supervision might be my least favorite aspect of FreeBSD, an OS I like overall. Not long ago, I wanted to avoid running a custom service that way on a fresh FreeBSD server. After researching my options, I found an adequate solution in the daemontools family. I'd heard of daemontools but hadn't paid much attention to it.

My service has been managed by runit and, most recently, nitro (https://github.com/leahneukirchen/nitro). Both have run as the service's user. They supervise the process and handle logging. I have found the design of daemontools and its derivatives runit and nitro elegant; it lives up to the reputation.


I have been using daemontools for managing my services on FreeBSD servers that have run 24/7 for almost a quarter of century, with down times of an hour or so only at intervals of a few years of continuous running, whenever I made a hardware upgrade or a complete OS replacement (by passing to another major version of FreeBSD).

Now there are several daemontools derivatives that bring it more up-to-date, but even the ancient original version did most of one would need for reliable service management.


You can use so-called "exec magic" instead of `env -S`. Here is an explanation with Python examples: https://dbohdan.com/scripts-with-dependencies#exec-magic (disclosure: my site). In short:

  #! /bin/sh
  "exec" "/usr/bin/env" "uv" "run" "--quiet" "--script" "$0" "$@"
  # /// script
  # dependencies = [
  #   "cowsay",
  # ]
  # ///
  import cowsay
  cowsay.cow("Hello, world!")
On systems that can't run uv, like NetBSD and OpenBSD, switch to pipx:

  #! /bin/sh
  "exec" "/usr/bin/env" "pipx" "run" "$0" "$@"
  # ...


According to https://old.reddit.com/r/thinkpad/comments/1d13sb6/should_i_...:

> - Display lid is very fragile at the top where the wifi antennas are and can easily crack there


Yes, if you look at a photo of the X220 lid, what looks like a cosmetic accent across the lid near screen-top is actually a seam, between the nice alloy traditional lid, and some plastic that's barely held on, painted to look the same. Even minor impact can break the little plastic screw hole tabs that hold the screen-top edge of the lid. Absolutely not what you want from a ThinkPad, which has a legacy of being durable.

https://www.reddit.com/media?url=https%3A%2F%2Fpreview.redd....

A disappointing thing about this is that someone changed the design, to this, to be more fragile and non-ThinkPad. In this way, it's similar to the series of regression changes to the keyboard, and now the TrackPoint.


I notice again I haven't internalized how much https://tvtropes.org/pmwiki/pmwiki.php/Main/SuspiciouslySpec... really happens.


> We already have FreeBSD CI; machines for the other 3 are arriving at my place tomorrow as it happens.

That's great. I hope it works out, and you have CI for NetBSD, OpenBSD, and illumos, too.

Go's support for NetBSD has been a big boon to the more casual NetBSD user who isn't going to maintain a port. It means a random Go open-source project you use probably works on NetBSD already, or if it doesn't, it can be fixed upstream. Maybe Zig could play a similar role.

It's a shame GitHub doesn't have native CI even for FreeBSD on x86-64. I can see the economic case against it, of course. That said, the third-party Cross-Platform GitHub Action (https://github.com/cross-platform-actions/action) has made Free/Net/OpenBSD CI practical for me. I have used it in many projects. The developer is currently working on OmniOS support in https://github.com/cross-platform-actions/omnios-builder.


> Go's support for NetBSD has been a big boon to the more casual NetBSD user who isn't going to maintain a port. It means a random Go open-source project you use probably works on NetBSD already, or if it doesn't, it can be fixed upstream. Maybe Zig could play a similar role.

In fact, we do already have cross-compilation support for NetBSD (and FreeBSD). But we currently only "test" NetBSD by building the language behavior tests and standard library tests for it on Linux, i.e. we don't actually run them, nor do we build the compiler itself for NetBSD. Native CI machines will allow us to fill that gap.

As it happens, Go's cross-compilation support does indeed make our lives easier for provisioning CI machines since we can build the Forgejo Runner for all of them from one machine: https://codeberg.org/ziglang/runner/releases/tag/v12.0.0


> For coding, you can use AI to write your code. For software engineering, you can't.

This is a pretty common sentiment. I think it equates using AI with vibe-coding, having AI write code without human review. I'd suggest amending your rule to this:

> For coding, you can use AI. For software engineering, you can't.

You can use AI in a process compatible with software engineering. Prompt it carefully to generate a draft, then have a human review and rework it as needed before committing. If the AI-written code is poorly architected or redundant, the human can use the same AI to refactor and shape it.

Now, you can say this negates the productivity gains. It will necessarily negate some. My point is that the result is comparable to human-written software (such as it is).


100% this.

Just don't expect to get decent code often if you mostly rely on something like cursor's default model.

You literally get what you pay for.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: