Skip to content
HomeVideosBooksBlogs
AllTop postsTopics
Podcasts
HistoryListsWatch laterLiked videosFollowing

The videos, books, blogs and podcasts Hacker News keeps recommending, all in one place.

VideosBooksBlogsPodcastsAboutPrivacySettings

Data from Hacker News, HackerTube, HackerBooks, HackerBlogs and Open Library. Credits · Not affiliated with Y Combinator.

HomeVideosBooksBlogsPodcasts
Ctrl K
    A

    Andrew Moffat

    amoffat.github.io · Personal blog · on HN since 2013

    Andrew Moffat writes about his open source projects, including the Python sh module and the supertag tag-based filesystem, plus programming essays.

    Visit blogHN submissions
    ProgrammingOpen Source & Linux
    What HN says

    Commenters praise the sh module as excellent for using shell commands and pipes from Python, and call the supertag FAQ exceptionally well put together.

    Stats for nerds
    50HN people shared it
    13linked in comments
    80story points
    Jan 2025last shared
    2017people per year2025

    Top posts on HN

    1. 1
      Show HN: Reimagine the File System
      5 people · 51 points · first shared 2020 · 13 comments on HN
    2. 2
      Shell Scripting support for Python
      39 people · 12 points · first shared 2013 · Discussion on HN
    3. 3
      Why is it called a Fibonacci Heap?
      1 person · 5 points · first shared 2018 · Discussion on HN
    4. 4
      Vetted AI code is hard to justify
      3 people · 3 points · first shared 2026 · 2 comments on HN
    5. 5
      Show HN: Solve the Travelling Salesman Problem with the GPU
      1 person · 3 points · first shared 2017 · Discussion on HN
    6. 6
      WebGL Solver for the Travelling Salesman Problem
      1 person · 3 points · first shared 2017 · 2 comments on HN
    7. 7
      Travelling Salesman solver with WebGL
      1 person · 2 points · first shared 2017 · Discussion on HN
    8. 8
      Fight the Bug, Not the Tools
      1 person · 1 points · first shared 2019 · Discussion on HN
    9. 9
      Faq
      3 people · first shared 2017
    10. 10
      Faq
      2 people · first shared 2022

    What HN people wrote when they linked it

    • vlovich123Oct 2020

      You have to dig through the documentation a bit on the website but all the info is there[1]

      from sh import mysqldump
      from sh import gzip

      gzip(mysqldump("example_db", _piped=True), _out="dump.sql.gz")

      or if you don't want the magic import thing:

      import sh
      sh.gzip(sh.mysqldump("example_db", _piped=True), _out="dump.sql.gz")

      It's definitely foreign to shell scripting languages since the piping syntax is a bit different & you have to remember to do `_piped=True` since it's not parallel by default. But the default behavior is pipefail & exit on the command failing IIRC so it's more of a choose your poison thing (do you want a subtle perf issue or a subtle bug in your script not handling error states correctly). And I find it easier to read. + if you want to customize anything about gzip or not rely on needing the binary in the path, then you can just switch it to Python-native gzip pretty easily.

      That's my favorite feature. Conciseness if I'm just translating a script with progressive complexity options to migrate things that need more complexity or different requirements within the same script without having to rewrite it from scratch.

      [1] https://amoffat.github.io/sh/

    • theamkDec 2018

      Note that this recommends "sh" package, which made an _interesting_ decision to run processes in tty by default. This goes against unix conventions that batch processes should not be using tty, and breaks a number of utilities like git and systemctl. This is so bad that even their example from the front page is broken(!):

      $ python3
      >>> import sh
      >>> sh.git.show('HEAD').count('\n')
      49
      # Now resize your terminal window to be 10 lines tall
      >>> sh.git.show('HEAD').count('\n')
      9

      Yep, it truncated "git show" output to the height of your terminal window. Do you want this in your code?

      While you can append special flag for this, it is very easy to forget to do so, and the documentation does not help either. Their FAQ states that they are aware of the issue and won't fix it [0].

      So my advice is: stay away from "sh" package, as it makes it very simple to generate unreliable code. Instead, use built-in tools which are pretty nice and just a bit more verbose:

      >>> import subprocess
      >>> subprocess.check_output('git show HEAD', shell=True).decode().count('\n')
      49

      [0] https://amoffat.github.io/sh/sections/faq.html#why-is-tty-out-true-the-default

    • yjftsjthsd-hMar 2022

      On the contrary, I am 100% open to suggestions that BASH sucks. (Personally, I would have picked the inadequacies of `set -e` as my favorite ... unfortunate aspect.) My objection was very narrow: this specific article does a poor job at saying why shell sucks, and a worse job still at presenting Python as a superior alternative. That's not to say that good reasons to use something else don't exist, and it's not even to say that Python can't be that alternative. (Your sibling comments suggesting xonsh and https://amoffat.github.io/sh/ paint a fairly compelling way to actually move to python without losing the advantages of shell, for instance.)

    • imiricApr 2021

      Great, would that work with pipes and redirections too? At that point you might as well use sh[1] which is a more advanced abstraction. My issue with these approaches is that you'll inevitably hit a bug or limitation where just using a shell language would've been easier to maintain and more portable.

      Python has its uses, but replacing shell scripts is not one of them IMO. It it was then the problem didn't need to be a shell script to begin with (doesn't shell out often, needs complex data structures, etc.).

      [1]: https://amoffat.github.io/sh/

    • groby_bJan 2025

      If you mostly want to query and can live without the VFS, dogsheep[1] is your friend. It's a general tool to import lots of different data types into a personal sqlite instance, and dogsheep-photos[2] both extracts image metadata and uploads all the pics to S3 if you'd like.

      On my to-try list, there's also supertag[3], a tag-based filesystem that's mounted via FUSE

      [1] https://dogsheep.github.io/ [2] https://github.com/dogsheep/dogsheep-photos [3] https://amoffat.github.io/supertag/

    • argonauts12Jul 2020

      I've been migrating shell scripts to python and have found the 'sh' library invaluable for pulling in pure CLI commands from the bash script and adding to the python implementation. http://amoffat.github.io/sh/
      It's essentially an abstraction layer above subprocess. Quick example - to use ifconfig natively in python:

      from sh import ifconfig print(ifconfig("wlan0"))

    Related

    Ian Bickingblog.ianbicking.org107 people

    Firefox Was Always Enough

    Ian Bicking
    Personal · last shared 2026
    Brett Cannonsnarky.ca100 people

    Why Python 3 Exists

    Brett Cannon
    Personal · last shared 2026
    Trek10 Blogtrek10.com18 people

    Principles for Building New SaaS Products on AWS

    Trek10 Blog
    Company · last shared 2024
    LShift Bloglshift.net41 people

    Python quirks

    LShift Blog
    Company · last shared 2016
    Oils Blogoilshell.org156 people

    Kubernetes is our generation's Multics

    Oils Blog
    Company · last shared 2026
    Chris Wellonsnullprogram.com295 people

    Why Aren't There C Conferences?

    Chris Wellons
    Personal · last shared 2026
    Lambda the Ultimatelambda-the-ultimate.org615 people

    Simon Peyton Jones Elected into the Royal Society Fellowship

    Lambda the Ultimate
    Publication · last shared 2026
    Graham Jenkinsdarkcoding.net44 people

    Facebook’s code quality problem (2015)

    Graham Jenkins
    Personal · last shared 2025