[HN Gopher] I'm switching to Python and actually liking it
___________________________________________________________________
I'm switching to Python and actually liking it
Author : cesarsotovalero
Score : 302 points
Date : 2025-07-16 07:44 UTC (15 hours ago)
(HTM) web link (www.cesarsotovalero.net)
(TXT) w3m dump (www.cesarsotovalero.net)
| messe wrote:
| > the Python interpreter is natively integrated in all Unix
| distros
|
| It's included in the default install of most desktop/server Linux
| distros (with plenty of exceptions), but I don't believe any of
| the BSDs ship it in their base system.
|
| IIRC macOS used to have python 2 in its default install, but I
| vaguely recall that being deprecated and removed at some point.
| My only Mac is on the other side of the country at the moment, so
| I can't check myself.
| blitzar wrote:
| I dont think python is pre-installed on macOS now. (uv has
| replaced it for me)
|
| Edit: Unlike older versions of macOS that came with Python 2.7
| pre-installed, newer macOS versions (Catalina and later) no
| longer include Python pre-installed.
| oneeyedpigeon wrote:
| macOS dropped PHP recently too--doing a wonderful job of
| losing all that developer share that Apple was slowly
| building up.
| frizlab wrote:
| Why? Installing python and php can be done in 2 seconds
| with brew, and you have control over what you install
| instead of using whatever is in the system, with deprecated
| versions, etc. It is actually _much_ better now. System
| tool should be left to the system.
| est wrote:
| if you install commandline tools there's
|
| /Library/Developer/CommandLineTools/Library/Frameworks/Pyth
| on3.framework/
| wiseowise wrote:
| Virtually zero professional developers that I know use
| built in Python or PHP. Maybe it's good enough for
| occasional scripting purposes, though.
| stby wrote:
| I much prefer installing it myself, with the required
| version for my project and at a known and common location.
| comradesmith wrote:
| I think it's better for developers to not have conflicting
| system distributions.
|
| Though for a while there having built in interpreters was
| great for kids and learners.
| latexr wrote:
| Technically macOS doesn't come with Python pre-installed, but
| it does provide you with a simple path to do it.
|
| https://news.ycombinator.com/item?id=44580198
|
| The removal was in Monterey. Catalina and its successor Big
| Sur very much still had it. Catalina was the one that removed
| 32-bit support.
| tovazm wrote:
| I think they realised the security implications,
|
| you could just take a random person macbook, open the
| terminal and launch python3 -m http.server 3000 --directory
| ~
|
| then on the local network you could download all his files
| latexr wrote:
| If you have access to their MacBook and can open a
| terminal, even `rsync` (which comes preinstalled) would
| do the job.
|
| It seems much more likely to me they were just tired of
| having to manage the languages (and being constantly
| criticised they were behind) and simply chose to remove
| them.
| latexr wrote:
| Python 2 was removed in Monterey 12.3, which was incredibly
| stupid and disruptive as it caught everyone by surprise. We all
| knew Apple said they would remove it, but everyone was
| expecting them to be sensible and do it on a new major OS
| release, like they did with PHP, not mid-cycle.
|
| https://developer.apple.com/documentation/macos-release-note...
|
| I wonder if that kerfuffle is why they ended up not removing
| Ruby and Perl yet, despite the same promise. macOS' Ruby is
| around 2.6. Perl I somehow doubt they'll get to, as it's such
| an important part of Unix admin I bet they themselves use it
| somewhere.
|
| There is still a /usr/bin/python3 which is a shim. When you
| call it, if you don't have the Xcode Developer Tools you'll be
| asked to install them (it's a non-scary GUI dialog which takes
| two clicks) and then you're set. That is also a few versions
| behind the cutting edge, but it does get updated sometimes.
| WesolyKubeczek wrote:
| I think that by now we shouldn't take a .0 major release as a
| sign of what is really going to be present in macOS and
| what's not. The OS stabilizes around .4 or so, and in the
| meantime some deprecated things may get removed, too.
|
| They also have a habit of sometimes add or change some APIs
| mid-cycle, so you may see requirements for the latest Xcode
| being a mid-cycle version of the OS. Or how was it with Mac
| App Store, that not only itself, but the relevant APIs for
| programs distributed in it appeared in 10.6.4?
| v5v3 wrote:
| "the second best language for any job"
| tim-kt wrote:
| Meaning the first best language depends on the job?
| stefcoetzee wrote:
| Of course :)
| bravesoul2 wrote:
| There are many jobs where the .Net/Java/Go triad would be in
| the top 3. I lump them together as typed languages that are
| mainstream, performant, have a GC and a featured library.
| eurekin wrote:
| I'm at a java shop. All customer facing apps are in java. Our
| tools and glue code is mostly in python. Similar for data
| processing workflows
| bravesoul2 wrote:
| Yes that might demonstrate the point. Would Python be your
| second choice for the customer facing apps?
| eurekin wrote:
| Unfortunately, might not be easy in practice. It took
| years of effort to pass some certifications and audits
| and I don't think adding another language could be
| recouped now
| reedf1 wrote:
| > Python has done a good job of hiding its legacy ugliness (such
| as __init__, __new__, and similar aberrations), swettening its
| syntax to accomodate developers with good taste.
|
| What exactly is the problem with __init__ or __new__? @dataclass
| is very nice syntactic sugar, but are we arguing here that having
| _access_ to initializer /allocator/constructor dunder methods is
| "legacy ugliness"? This is the core of pythonic built-in aware
| python. Bizarre.
| wiseowise wrote:
| Bizarre is that you don't consider it ugly.
|
| Kotlin: constructor is either part of class definition or
| keyword constructor.
|
| Ruby: initialize
|
| JS: constructor
|
| Python: ______new______, _______init_______
|
| Literally this meme: https://knowyourmeme.com/memes/three-
| headed-dragon
| reedf1 wrote:
| I had honestly not considered that the author might have been
| talking about the _visual aesthetic_ of the dunder methods
| themselves. Honestly that has me a bit stumped; all I can say
| is that if you don 't like underscores, don't pick python.
| t43562 wrote:
| You don't call __init__ directly so the ugliness is limited
| to the definition which seems fairly minimal to me. It seems
| to be a naming convention for methods that are not invoked by
| name anywhere and that's at least informative when you're
| reading the class definition.
|
| IMO this is less horrendous than e.g. go's insistence that
| exported functions are indicated by a capital letter - that
| really affects code using the module not just the definition.
| NoboruWataya wrote:
| I like that magic method names generally all follow the same
| form so it's obvious that they are magic methods and not
| intended to be part of the public API. Whether that form uses
| double underscores or something else doesn't really matter to
| me as they are not being called directly.
| 63stack wrote:
| Would you consider a constructor magic though?
| lou1306 wrote:
| "Magic methods" is just the name people use for these
| special methods (another is dunder methods). They're
| "magic" because you do not call them by name, rather they
| are invoked by the interpreter in specific situations.
| dragonwriter wrote:
| Yes, it is magic the same way other magic methods are,
| that is, because it is syntactically special and callable
| (and primarily called by) a syntax other than
| <instance>.<method>(...) or <class>.<method>(instance,
| ...)
|
| Specifically, in the case of constructors, via
| <class>(...).
| fiedzia wrote:
| > it's obvious that they are magic methods and not intended
| to be part of the public API
|
| Is there an alternative API? No. This is public API
| regardless of anyone's intentions. Though "it's weird" is
| really not a very strong argument against it.
| trylist wrote:
| Public API refers to the user of the class, not the
| implementer. You never call __init__ directly. __new__
| allows modifying object creation itself for the
| implementer, but the user of the class will never call
| it.
| freehorse wrote:
| There are private and public methods. Private methods are
| only supposed to be called within other methods, as in
| privately. Public methods are the ones that are normally
| called through the code, repl, by the user or whatever.
| You are not supposed to write `myclass.__add__(x)`
| anywhere except where you define the class itself and its
| methods.
| Izkata wrote:
| There's actually 4 kinds: def foo(... #
| public def _foo(... # internal def __foo(...
| # munged def __foo__(... # magic
|
| Internal is more convention as the language doesn't
| really do anything with it, but it does with munged, and
| magic methods are specifically for things implemented in
| the language.
|
| Internal and munged don't exactly map to private and
| protected, but are kinda similar ish.
| freehorse wrote:
| Oh right. I am not really into python, had read some doc
| about naming conventions some poitns.
|
| In any case I actually like how one can use underscores
| to point on how exposed some method is supposed to be.
| Makes it simpler to actually know what to skip and what
| not.
| __MatrixMan__ wrote:
| There are several alternative API's. @dataclass is one,
| Pydantic offers another, there's also attrs, plus less
| general things like namedtuple.
|
| Admittedly it's obnoxious when you've got habits for one
| and you're on a team that uses another--totally flies in
| the face of the zen re: "there should be only one obvious
| way to do things".
|
| ...but that was always a rather ambitious goal anyway.
| I'm ok navigating the forest of alternative API's if it
| means not being locked into something that I can only
| change by choosing an entirely different language. I'm
| happy that it's very easy to tell when somebody is
| mucking about with python internals vs when they're
| mucking about with some library or other.
| yunwal wrote:
| @dataclass does a very specific subset of what overriding
| dunder methods does. It's not duplicating an abstraction
| it's layering them
| dncornholio wrote:
| I have found to believe that ugly and beautiful are
| irrelevant. As long as it's doing the job and not cause major
| headaches. Life is too short to worry about syntax.
| orphea wrote:
| Right? I'm kind of surprised that a few underscores invoke
| such strong emotions in people.
| nottorp wrote:
| > Life is too short to worry about syntax.
|
| Every programming language you use will annoy you in some
| way. You stop caring after a few of them.
| timeon wrote:
| Can you elaborate bit what is the problem here? Is it shape
| of the characters or something else?
| brabel wrote:
| Amazing. If you need to ask this question I am guessing you
| have spent too long with Python . No other language uses
| this underscore madness for special methods or otherwise.
| Because it's just , I don't know a more appropriate word
| for it , stupid.
| Octoth0rpe wrote:
| Oh yes they do:
| https://www.php.net/manual/en/language.oop5.magic.php
|
| The programming languages world is broad/varied enough
| that any statement like "no other language does this!" is
| almost certainly wrong (outside of esoteric languages,
| which python and php most certainly are not)
| deathanatos wrote:
| Lua, too: __add, __sub, __mul, __div,
| __mod, __pow, __unm, __idiv __band, __bor, __bxor,
| __bnot, __shl, __shr __concat, __len __eq,
| __lt, __le __index, __newindex, __call __gc,
| __close, __mode, __name
| Twirrim wrote:
| What's actually amazing is how you're unable to answer a
| straight question.
|
| If you call something "stupid" it doesn't really convey
| anything meaningful, especially not in the way you're
| using there, it comes across as "I don't actually have a
| reason I don't like it, I just don't".
| DrJosiah wrote:
| I mean, Python is dynamic. Here, have this: https://gist.
| github.com/josiahcarlson/39ed816e80108093d585df...
|
| Now you don't need to write your double-underscore
| methods ever again, if you don't want to.
| thesuperbigfrog wrote:
| Most C and C++ compilers use similarly named macros:
|
| https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-
| Macro...
| dumah wrote:
| I'm not sure why you're comparing __new__ to constructors in
| other languages.
|
| Ruby has the same thing but it's called 'new'.
|
| Implementing the type of customization (idiomatically) that
| __new__ provides in Kotlin and JS isn't any cleaner.
| parentheses wrote:
| That's kind of the point. These methods are never meant to be
| called directly. They're used to desugar.
|
| I think it's fairly short sighted to criticize these. FWIW, I
| also did that the first time I wrote Python. Other languages
| that do similar things provide a useful transparency.
| NewsaHackO wrote:
| I don't think anyone is criticizing its utility, just that
| the syntax of 2-5(?) underscores in a row isn't something
| that is DX friendly.
| dragonwriter wrote:
| The syntax is exactly two, not 2-5.
| JKCalhoun wrote:
| I think the point was: who can know by looking at it.
| gcbirzan wrote:
| I mean, maybe you should use a font that doesn't make it
| hard to figure that out. Next you're gonna say we should
| ban 0s and Os, Is and ls, because your font doesn't allow
| you to figure out which one it is.
| dragonwriter wrote:
| Anyone using a monospacdd font, a font where underscores
| are separated, or a run-together proportional font that
| they are even a little bit familiar with, because of the
| relative width of underscores and other characters.
|
| Which, between them, covers approximately everyone.
| hiAndrewQuinn wrote:
| The ugliness is intentional. Nobody _wants_ to name their
| cool new variable __hot__singleton__in__your__area__.
| __MatrixMan__ wrote:
| It's like the bright orange garments that hunters wear, the
| ugliness is sort of the point. It says "this is a different
| sort of thing."
| ddejohn wrote:
| > It's like the bright orange garments that hunters wear,
| the ugliness is sort of the point.
|
| Ugliness is not the point of hi-vis vests lol, the point is
| to not get shot by other hunters.
| __MatrixMan__ wrote:
| ...by being as shockingly contrasting with their
| environment as possible. Maybe your aesthetics differ,
| but I find it quite ugly. If it wasn't, it wouldn't grab
| my attention so well. Wearing something shockingly ugly
| is a great way to not be mistaken for a deer.
|
| By contrast, I find a well camouflaged deer quite
| beautiful--once I notice it at all. The beauty comes from
| the way that it is so clearly a thing of its
| surroundings. Nothing at all like a bright orange hat.
| ddejohn wrote:
| > Wearing something shockingly ugly is a great way to not
| be mistaken for a deer.
|
| Sure... yes the bright orange is ugly, but it's not the
| _ugliness_ that prevents you from getting shot, it 's the
| bright unnatural color. Other hunters aren't thinking "oh
| that's really ugly, it must not be something I can shoot"
| they're thinking "bright orange means person, I should
| not fire my rifle in that direction".
|
| > If it wasn't, it wouldn't grab my attention so well.
|
| Are you saying that if you thought the bright orange was
| pretty it wouldn't occur to you not to fire your gun in
| its direction?
| guhcampos wrote:
| Some-other-language-user complaining about python
| ugliness:_____new_____ and _____init_____
|
| Same-other-language-user:
|
| ((()))()()()({}{}{{(((())){}}}}{}{}{};;;;();)(;}}}
|
| *not supposed to be correct syntax, it's just a joke
| slightwinder wrote:
| As if other language don't have their warts.. Ruby and
| Javascript for example have hideous syntax, comparing this
| with some special naming is quite bizarre.
|
| But who cares? It's syntax, it has its purpose.
| moffkalast wrote:
| I would think the dumber thing is having to create an empty
| file called __init__.py for a package to register as a
| package. And relative imports being completely fubar.
| kolanos wrote:
| > I would think the dumber thing is having to create an
| empty file called __init__.py for a package to register as
| a package.
|
| This hasn't been true since Python 3.3. You no longer need
| a __init__.py for Python to recognize a module, but it can
| still be useful in many cases.
| maleldil wrote:
| This is incorrect.
|
| > The __init__.py files are required to make Python treat
| directories containing the file as packages (unless using
| a namespace package, a relatively advanced feature).
|
| https://docs.python.org/3/tutorial/modules.html
| mixmastamyk wrote:
| The point is to keep them out of the object namespace, and
| works well for that.
| DrJosiah wrote:
| I mean, it's never been a problem for me in my 26 years of
| Python, but if it is such a big deal for you, maybe you
| should consider this: https://gist.github.com/josiahcarlson/3
| 9ed816e80108093d585df...
|
| I wrote it in about an hour and a half. It seems to work in
| Python 3.6 and 3.12. Now you never need to write another
| double-underscore magic method again.
| adw wrote:
| Fewer characters than "initialize" or "constructor", clearly
| marked as being "not a normal method". Python is _better_
| here.
| dragonwriter wrote:
| If you felt your argument about __new__ and __init__ was
| valid, you probably would have used the actual names and not
| hyperbolic exaggerations.
| thaumasiotes wrote:
| Probably the system of giving special meaning to what are
| otherwise ordinary identifiers. __ isn't a reserved keyword in
| Python or anything. But there's a set of conventions you're
| supposed to follow when naming methods and attributes, and
| they're visibly artificial. It would be cleaner to make the
| features that are a special part of the language definition
| also a special part of the language syntax instead of running
| them in indistinguishably with other nonsimilar things.
|
| In C++, if you want to define the binary + operator on a class,
| you give the class a method with the special name `operator+`.
| In Python, to do the same thing, you give the class a method
| with the pseudo-special name `__add__`. You don't think the
| Python way is worse?
| reverius42 wrote:
| I'm not sure how "operator+" is supposed to be appreciably
| different from "__add__".
| brabel wrote:
| One is a sensible choice a human might pick. The other is
| not.
| orphea wrote:
| Both are doing their job just fine?
| acdha wrote:
| So who were the non-humans who picked the one you don't
| like?
| dragonwriter wrote:
| They are both sensible choices that a human _did_ pick,
| that 's how they got into their respective languages.
| WesolyKubeczek wrote:
| They have different locality of behavior, for one.
| acdha wrote:
| > You don't think the Python way is worse?
|
| Have you considered how much familiarity might shape your
| reaction to the two? Both are specific patterns with
| arbitrary restrictions which new learners have to
| internalize, and that's a fairly advanced task most people
| won't hit until they are familiar with the language syntax.
|
| Here's a counter argument: the Python methods are normal
| method declarations whereas C++ developers have to learn that
| "operator=" means something different than what "operator ="
| (or any other assignment statement) would mean, and that this
| is the only context where you can use those reserved symbols
| in method names.
|
| To be clear, I don't think either of these is a big deal -
| the concepts and usage are harder to learn than the
| declaration syntax - but I think it's incredibly easy to
| conflate familiarity with ease of acquisition for things like
| this.
| thaumasiotes wrote:
| > Have you considered how much familiarity might shape your
| reaction to the two?
|
| It doesn't.
|
| > Both are specific patterns with arbitrary restrictions
| which new learners have to internalize, and that's a fairly
| advanced task most people won't hit until they are familiar
| with the language syntax.
|
| No, the Python methods are just ordinary methods with valid
| names. What 'arbitrary restrictions' are you referring to?
| acdha wrote:
| The arbitrary restriction is that you have to just learn
| a specific pattern and follow it. I can't have my Python
| class use "addition" if I hate underscores or my C++ code
| use "mathematical_division" if I'm horribly pedantic. In
| both cases, it's just a particular design decision by the
| language developers I have to learn, and in both cases I
| won't think much of it after the initial acclimation.
| yunwal wrote:
| Python you have to learn something arbitrary for each
| dunder method you want to define/override. + --> __add__,
| * ---> __mul__, etc
|
| C++ it's just one pattern to learn, x -> operatorx
| kemayo wrote:
| Funnily enough, _just_ starting your class method /variable
| name with __ does do magic things as a pseudo-keyword.
| Specifically, it mangles the name for callers outside of that
| class -- `self.__foo` would need to be accessed as
| `obj._ClassName__foo`. It's python's approach to having
| private methods, while remaining somewhat ideologically
| opposed to them existing.
|
| This doesn't apply to the dunder methods, though. They're
| magically exempt from this magical mangling, so you could
| call them directly if you wanted. -\\_(tsu)_/-
|
| > You don't think the Python way is worse?
|
| They seem about equivalent? I don't see any real reason to
| pick one or the other, beyond personal preferences.
| wasabi991011 wrote:
| What's the use case for __foo -> _ClassName__foo? I've used
| python a bunch but never this feature, so I'm curious.
| kstrauser wrote:
| It makes it nearly impossible to reference that attribute
| by accident. Basically, if class Foo defines
| "self.__bar", the Python interpreter sees the leading
| "__" and mangles it. It's the lightweight equivalent of a
| private attribute in other languages, with the difference
| that Python will _let_ you attempt to access it anyway.
| But if you do, and it makes your code utterly brittle and
| prone to explosion, no one will give you sympathy or help
| you fix it. They 're much more likely to tell you not to
| do that.
| dragonwriter wrote:
| It prevents accidentally overriding the member in
| subclasses which can prevent private implementation
| details of parent classes from being accidentally
| interfered with by child classes.
|
| As composition over inheritance becomes more idiomatic,
| there are probably less places where this matters, but as
| long as inheritance is used at all it can be useful.
| antod wrote:
| It's as close as they'll get to private methods while
| still having the "we're all consenting adults" philosophy
| that doesn't prevent you doing something dumb. Or if you
| use this and it breaks, you can't say you weren't warned.
| DrJosiah wrote:
| Not when this can be done: https://gist.github.com/josiahcarl
| son/39ed816e80108093d585df...
|
| Take a deep breath.
| andyjohnson0 wrote:
| > What exactly is the problem with __init__ or __new__?
| @dataclass is very nice syntactic sugar, but are we arguing
| here that having access to initializer/allocator/constructor
| dunder methods is "legacy ugliness"?
|
| My read was that the "ugliness" was in the method naming, and
| specifically the double underscores, not the availability of
| the methods themselves.
| lenerdenator wrote:
| I've been doing Python professionally for a while (~10-ish
| years in backend web dev and file processing), and while I
| don't like how exactly the author described dunder methods as
| "legacy", it's still not a language facility I reach out to
| often because, well, it's sort of odd coming from a C#
| background. The author has blog posts about Java, which isn't
| that different from C#, so maybe that's the reason.
|
| Maybe as I grow to think of the "big picture" architecture-wise
| with my code, I will start incorporating dunders, but until
| then...
| smcleod wrote:
| Python as a language is nice. Python's version and package
| management is nothing short of a nightmare.
| est wrote:
| Python's package management is OK. The main culprit is .so
| libraries
|
| Think JNI or cgo management.
| t43562 wrote:
| Yes, I've never really understood the complaint about python
| packaging - building native code is not something that is
| ever easy to guarantee across multiple distributions and
| operating systems.
|
| Those native packages can be in any language and require any
| odd combination of tools to build. Who has truly solved that
| problem?
| nikisweeting wrote:
| wheels, conda, docker, firecracker, unikernel, flatpak
| t43562 wrote:
| flatpak, docker ? i.e. include an almost complete
| distribution just to make one package work? but what if
| you want that package to work in the distribution you
| have now? What if you need 2 different packages that are
| in different flatpacks or different docker images?
| staunton wrote:
| Set them up, each in its own container, and use GRPC to
| communicate between them...
|
| (Not even kidding, I've seen people do this)
| t43562 wrote:
| Goodness gracious!
| staunton wrote:
| Well, if you're using GRPC _anyway_ , and have the
| protocol buffers _already_... It 's hard to resist the
| temptation after a few hours of installing broken package
| versions.
|
| Incidentally, I suspect this is the spiritual origin of
| microservoces...
| nikisweeting wrote:
| obviously don't try those _first_ I 'm just saying
| there's a stack of options to work with for any level of
| isolation you desire.
|
| start with wheels if you just want pre-built binaries,
| move up to conda if you need arch and OS-specific C libs
| that depend on system packages, flatpack or docker if you
| dont want those to mess up your host, or
| unikernel/firecracker/VMs if you need kernel modules or
| hardware virtualization.
| Orygin wrote:
| If you don't need to link C lib, you can build any
| combination of arch and OS for a golang program. The
| default tooling allows you to do so easily.
|
| If you need to link a C lib, there are ways to set it up to
| compile other OS (and maybe other archs).
| RamblingCTO wrote:
| I'll throw in BLAS and LAPACK. Fuck, what a nightmare it
| always has been to get scipy running. I've always ended up
| with a wild mix of conda and pip installed shit that just
| wouldn't work.
| macawfish wrote:
| It is not okay (maybe uv fixes this?)
| jcattle wrote:
| Going to be honest: With uv it really isn't that bad anymore.
| Sure, the whole packaging ecosystem is still really bad, but uv
| abstracts over most of it. Unless you're doing some really
| esoteric stuff you'll be just fine.
| xyzsparetimexyz wrote:
| Using a nix devshell has worked out well for scripts for me so
| far. I haven't figured out what that workflow is like for
| larger projects though. I'm not interested in learning Uv
| smallerfish wrote:
| There's nothing to learn. Get Claude code to install uv into
| your devshell and cut over your requirements. 5 minutes.
| expenses3 wrote:
| AI? :vomit_emoji:
| __MatrixMan__ wrote:
| Or do it yourself, 10 minutes
| __MatrixMan__ wrote:
| As a nix user, you hardly need to know uv, but you might
| later need to know how to work together with non-nix-users
| who use uv. It's easy.
|
| There will be a file: uv.lock You can use uv2nix to get a
| single nix package for all the project's python dependencies,
| which you can then add to your devshell like anything else
| you find in nixpkgs (e.g. right alongside uv itself). It ends
| up being two or three lines of code to actually get the
| package, but you can just point a LLM at the uv2nix docs and
| at your flake.nix and it'll figure them out for you.
|
| Your devshell will then track with changes that other devs
| make to that project's dependencies. If you want to modify
| them... edit pyproject.toml # package names
| and versions uv lock # map names and
| versions to hashes (nix needs hashes, finds them in uv.lock)
| nix flake lock # update flake.lock based on uv.lock
| nix develop # now your devshell has it too
|
| This way you're not maintaining separate sources of truth for
| what the project depends on, and the muggles need not think
| about your nix wizardy at all.
| expenses3 wrote:
| Didn't I say I wasn't interested?
| __MatrixMan__ wrote:
| You created a place where the interaction between nix
| devshells and uv was relevant, I put something there to
| help passers-by that might be interested in those topics.
| It wasn't actually _for_ you.
| lazzlazzlazz wrote:
| This hasn't really been true for a while now. `uv` has
| radically improved the experience.
| cedws wrote:
| There's still 20 years of projects using everything that
| became before uv. They didn't upgrade the moment uv came into
| existence. Data science-land still uses other rubbish too.
| zimpenfish wrote:
| > They didn't upgrade the moment uv came into existence.
|
| There's also projects that can't use `uv` because it
| doesn't like their current `requirements.txt`[0] and I have
| no bandwidth to try and figure out how to work around it.
|
| [0] We have an install from `git+https` in there and it
| objects strongly for some reason. Internet searches have
| not revealed anything helpful.
| bootsmann wrote:
| Unrelated to uv but the problem with having a git ref in
| requirements.txt is that pip will treat it as a fixed
| version so it will strictly narrow the other dependencies
| it can resolve, which gets exceptionally difficult to
| reason about once that packages also loads a package from
| another git ref. Throwing everything into codeartifact
| (or equivalent on other clouds) is better longterm.
| zanie wrote:
| If you open even a brief issue and tag me @zanieb I'm
| happy to take a look!
| bborud wrote:
| For the last 20 years that has been the mantra. Some X
| "solves" all the problems.
|
| Except it doesn't. It just creates another X that is popular
| for a while, and doesn't somehow retroactively "fix" all the
| chaotic projects that are a nightmare to install and upgrade.
| Yes, I understand people like Python. Yes, I understand the
| LLM bros love it. But in a real production environment, for
| real applications, you still want to avoid it because it
| isn't particularly easy to create robust systems for
| industrial use. You may survive if you can contain the
| madness in a datacenter somewhere and have people babysit it.
| bodge5000 wrote:
| I can get that Pythons not for everyone, it certainly has
| its flaws and maybe uv is just another transient solution
| which will come and go and others have. I might disagree,
| but I can accept that. What I can't accept is the idea that
| it should be avoided for real production environments,
| which is frankly a bit ridiculous considering all the real
| applications and real production environments running on
| Python.
| bbkane wrote:
| I think that's true until it isn't, and people are really
| rallying around uv.
|
| Here's to hoping it manages to actually solve the Python
| packagig issue (and lots of people are saying it already
| has for their use cases)!
| turtlebits wrote:
| I've ignored the trends and just used the bog standard
| requirements.txt with pip and a virtualenv and have had no
| problems in the past 10+ years. Either way, you always want
| to catch production deploys if something breaks.
| davepeck wrote:
| > But in a real production environment, for real
| applications, you still want to avoid it because it isn't
| particularly easy to create robust systems for industrial
| use.
|
| This is silly and seems to discount the massive Python
| codebases found in "real production environment"s
| throughout the tech industry and beyond, some of which are
| singlehandedly the codebases behind $1B+ ventures and, I'd
| wager, many of which are "robust" and fit for "industrial
| use" without babysitting just because they're Python.
|
| (I get not liking a given language or its ecosystem, but I
| suspect I could rewrite the same reply for just about any
| of the top 10-ish most commonly used languages today.)
| zanellato19 wrote:
| Some of the biggest codebases in the world are in Python,
| this is a bizarre statement that reeks of the hn
| superiority complex.
| viccis wrote:
| >Except it doesn't.
|
| That is only true if you never reexamine the universality
| of your statement. I promise that it is possible to "solve"
| the mess that was Python's ecosystem, that uv has largely
| done so, and that your preconceptions are holding you back
| from taking advantage of it.
| timw4mail wrote:
| It's like the (usually) interpreted equivalent to C/C++. There
| are lots of 'standard' package management choices.
|
| And it seems like the package resolution is finally local by
| default, although that requires a 'virtualenv', which seems to
| be a legacy of the global packaging system.
| __MatrixMan__ wrote:
| I expect that for every two python users who know what `pip`
| is, there are three who are discouraged from thinking about the
| environment at all. Given that, focusing on the language and
| not the packaging is the right choice. Packaging is most often
| somebody else's problem.
|
| It's just HN users are more likely to be that somebody else.
| Probably we have to deal with non-python dependencies _anyway_
| so we 're reaching for bigger hammers like docker or nix. It
| would be nice if there wasn't a mess of python package
| managers, but whichever one I use ends up being a somewhat
| unimportant middle-layer anyway.
| polotics wrote:
| It's funny, I'm the opposite: LLMs have made it easy to draft
| something in Python, then translate to a more appropriate
| language for the target problem-domain, for example Go.
| brabel wrote:
| Agree . We had training to learn how LLM applications can be
| developed and it was obviously in Python. Never liked Python
| but between dependencies issues (the demo project used uv but
| somehow the author forgot to declare some dependencies which
| she probably had installed globally) which cost hours of
| everyone's time, and the persistent magic going on (pipe
| operators that do nothing similar to unix pipes, wtf!,
| puydantic shit just to declare a data type with metadata and
| lots of things like this) nearly everyone immediately switched
| to a typed language like Kotlin (they have a nice AI framework)
| as soon as we got the basics of how things work.
| LtWorf wrote:
| Is go the language that doesn't include a module to do mmap and
| doesn't include a module to place binary data into a struct?
|
| If you want to read binary files, you can use C or python, but
| not go (unless you use segfault prone 3rd party libraries of
| very dubious quality, of course).
| revskill wrote:
| So, i don't get it, now i still need to have a uv venv ?
| akkad33 wrote:
| The principle of uv as much as I understand is to not tinker
| with virtual environments. With commands like uv run, uv sync
| etc you shouldn't have to worry about the virtual env and
| whether it's activated etc. if you are in a project, it will
| automatically pick up the right Python version . However if you
| want to do something not possible through those commands you
| can still get down to the virtual env. Plus for auto complete
| in IDEs you generally need to select the venv
| mpeg wrote:
| I use this vscode extension called "python envy" that changes
| venv automatically depending on which folder of a monorepo
| you are in, it's great! Wish vscode had it built-in
| akkad33 wrote:
| Never heard of it, will try. Thanks
| blitzar wrote:
| You install uv not python, you use "uv run <file>" instead of
| "python <file>", you dont think about anything else.
| Vaslo wrote:
| If you are working in Data Science/ML its the best bet for
| handling dependencies in your project compared to the rest of
| the tools. Its use has exploded, especially because you can do
| 'uv pip whatever' if you insist on using pip.
| andrewstuart wrote:
| Said with a note of surprise?
|
| Made me think this is probably normally a Ruby developer
| indoctrinated against Python. The article doesn't seem to say
| what they have come from.
| drewcoo wrote:
| > Ruby developer indoctrinated against Python
|
| Ruby devs think about code differently. Like Perl, they embrace
| TIMTOWTDI.
|
| https://perl.fandom.com/wiki/TIMTOWTDI
|
| Also, there's a pride in writing elegant code as opposed to
| following "Pythonic" conventions. Excellence is not conformity.
|
| I use Python a lot more often now because it's seen as simpler
| and more approachable and easier to force compliance. I miss
| Ruby.
| t43562 wrote:
| IMO "pythonic" is mostly about using the features the
| language has rather than trying to treat it as if it was Java
| or C++.
|
| Having said that, in reviews you do get lazy comments like
| "not pythonic" or "not best practises" which often boil down
| to the reviewer just not liking something and being too much
| of an *** to say why. This is supposed to be a total shutdown
| that you cannot argue with and it's the kind of thing that
| might put you off the term "pythonic" for life.
|
| "There should be one-- and preferably only one --obvious way
| to do it."
|
| This is probably the core thing you might have issue with but
| I think its not really about conforming in how you write your
| own code but about the thing you make being easy for others
| to use.
| greener_grass wrote:
| I love this sentiment:
|
| > There should be one-- and preferably only one --obvious
| way to do it.
|
| But I often _don 't_ think the Pythonic way is a very good
| way to do it. And this leaves you a bit stuck!
| Mawr wrote:
| > Like Perl, they embrace TIMTOWTDI.
|
| Yeah, and it's the wrong approach. Of course, you can have
| whatever preference you want, but in terms of engineering,
| it's plain wrong.
| wiseowise wrote:
| There's a footnote:
|
| > If you know me, you know I used to be mostly a
| Java/JavaScript/R kind of guy. -
| riffraff wrote:
| It's in the footnotes, they're a java/javascript/R dev.
| xandrius wrote:
| So, if you don't fancy Python you must be labeled a Ruby
| developer? Weird take.
| bravesoul2 wrote:
| I like Python for the language, and for a lot of jobs the
| threading model limitations do not matter. Its a great language
| to get stuff done. I find the package management story
| challenging but I will try uv next time!
| sudosays wrote:
| If you haven't already you should check out uv:
| https://github.com/astral-sh/uv
|
| It solves a lot of the package management headaches for me.
| rich_sasha wrote:
| I resisted pipx, poetry, anaconda and probably some other
| things, as I didn't see the point over venv+pip. But uv is just
| so damn good, there's no going back.
| gjvc wrote:
| pipdeptree is all you need for many things, but uv is such a
| joy to use it's hard to resist, sure.
| bootsmann wrote:
| Feel like pipx walked so uv could run, it popularized the
| idea of abstracting the environment management away from the
| user.
| zeppelin101 wrote:
| pipx is still the best tool for standalone utility type of
| packages: "yt-dlp", "glances" (like htop), etc.
| asa400 wrote:
| You can, however, use uv for this, e.g., `uvx yt-dlp`
| works like it would in pipx.
|
| https://docs.astral.sh/uv/guides/tools/
| Roark66 wrote:
| From what? It would be useful to mention towards the front of the
| post so we know what is the context in which you approach python.
|
| I've switched to python primarily (from perl) in early 2010s (I
| think my first "seriously" used version was 2.6. This is mostly
| for system management, monitoring, and data transformation
| /visualisation. Nothing fancy like AI back then in a work
| setting.
|
| I found the biggest impact was not so much on writing code but on
| it remaining readable for a very long time, even if it was
| created hastily "just get this working now" style. Especially in
| a team.
|
| Python is still one of my favourites and the first tool I reach
| if bash is not enough for what I'm trying to do.
| pyman wrote:
| From what I was told, Python was originally seen as a Swiss Army
| knife for sysadmins. It started gaining more traction when
| Canonical adopted it as the main language for Ubuntu 4.10 in
| 2004.
|
| Then, in 2005, Guido van Rossum was hired by Google to work on
| Google Cloud. That opened the door for wider adoption in
| academia, since Python had strong math libraries and integrated
| well with tools researchers were already using, like Hadoop,
| right around the time big data and ML were starting to take off.
|
| Also, between 2005 and 2006, two important things happened: Ruby
| on Rails came out and inspired Django, which was starting to gain
| popularity, and web developers were getting tired of Perl's messy
| syntax. That's how Python quickly became a solid choice not just
| for server-side scripts, but for building proper web apps. In the
| meantime, another language that could be embedded directly into
| HTML was storming the web: PHP. Its syntax was similar to
| JavaScript, it was easy to pick up, lowered the barrier to entry
| for software development, worked straight out of the box, and
| didn't require thousands of print statements to get things done.
|
| The 3 Ps made history. According to programmers from 20 years
| ago, they were like religions. Each had its own philosophy and a
| loyal group of followers crusading online, getting into heated
| debates, all trying to win over more adopters. The new generation
| of devs is more pragmatic. These days it's less about language
| wars and more about picking the right tool for the job.
| darkstar_16 wrote:
| > These days it's less about language wars and more about
| picking the right tool for the job
|
| You should talk to the Java advocates in my company :) The
| language wars are still around, it's just Java vs the rest now.
| pyman wrote:
| One of my colleagues, a retired programmer who spent 20 years
| at Microsoft, told my students that it used to be Java vs
| Visual Basic, until Microsoft brought in the big guns, like
| Anders Hejlsberg. That's when it turned into Java vs .NET,
| and things really started to heat up :)
| wiseowise wrote:
| Java unequivocally won the war, though.
| adw wrote:
| C# is the Java of Lua (thanks to Unity) which will never
| not be weird.
| tgv wrote:
| Python's success is entirely due to entry-level programming
| courses. They all switched to Python, because you have to
| explain less. I don't think I heard about web servers in Python
| before 2012. I suppose a 2005 computer wouldn't be able to
| serve a Python backend smoothly.
|
| PHP's popularity isn't really from 2005-2006. It was popular at
| the end of the 90s, and it looks like JS as much as it looks
| like a potato.
| theshrike79 wrote:
| With python you can just go: 'print "hello, world!"' and
| that's a full-ass program
|
| You run it by saying `python hello.py`.
|
| Compare that to the amount of crap you need(ed) with 2005
| Java just to have something running.
|
| The shittiness of ActivePython and generally getting python
| to run on Windows were a bit of a hurdle, but still it was
| easier than the competition
| taeric wrote:
| I mean, it isn't like you couldn't get similarly terse
| scripts in other languages. Common LISP, as an easy example
| people love to beat up on.
| nottorp wrote:
| You could, but then they deprecated the paranthesis less
| form in 3.x :)
| icedchai wrote:
| Sure, but you could've done the same thing with perl in the
| 80's and 90's.
| pyman wrote:
| > Python's success is entirely due to entry-level programming
| courses.
|
| Yeah, after 2008. And by 2014, it had overtaken Java in many
| CS programs. But I was referring to the events that led to
| that.
| stevesimmons wrote:
| > I suppose a 2005 computer wouldn't be able to serve a
| Python backend smoothly.
|
| Python had web servers from 2000, including Jim Fulton's Zope
| (really a full framework for a content management system) and
| in 2002 Remi Delon's CherryPy.
|
| Both were useful for their day, well supported by web hosting
| companies, and certainly very lightweight compared to
| commercial Java systems that typically needed beefy Sun
| Solaris servers.
| antod wrote:
| I'd forgotten about CherryPy until Turbogears was mentioned
| the other day in the Django birthday thread.
|
| But yeah Python was on an upswing for webdev and sysadmin
| (early DevOps?) tooling, but took quite a hit with Ruby eg
| Rails, Puppet, Vagrant and Chef etc.
|
| But Python hung on and had a comeback due to data science
| tooling, and Ruby losing it's hype to node for webdev and
| golang for the devops stuff.
| sylens wrote:
| In my experience AWS also contributes a lot to this. Boto3 is
| a great library for interacting with AWS services
| wiseowise wrote:
| > Python's success is entirely due to entry-level programming
| courses. They all switched to Python, because you have to
| explain less.
|
| Nonsense.
|
| > I don't think I heard about web servers in Python before
| 2012.
|
| More nonsense.
|
| > I suppose a 2005 computer wouldn't be able to serve a
| Python backend smoothly.
|
| Extreme nonsense.
|
| https://medium.com/signal-v-noise/ruby-has-been-fast-
| enough-...
|
| And this is when Python was edging Ruby performance wise.
| MoreQARespect wrote:
| This is entirely backward. They all started switching when
| python was already immensely popular after the popularity
| boosts given by sysadmin, django and numerical/datascience
| users.
| __rito__ wrote:
| This is what I have seen as well. When Python became
| ubiquitous in the industry, they started teaching it in the
| colleges.
|
| I come from a core science background. I studied Physics.
| And it was like this in my institute: FORTRAN -> A lot of
| C, small amount of FORTRAN -> C -> Python. I was taught C,
| but from the exact next year, it was switched to the Python
| ecosystem.
|
| It was done much later when Python became the standard in
| research universities, the language of recent research
| papers, etc.
|
| A generation of Scienctists learned C/FORTRAN/MATLAB in
| college/grad school as it was taught, but they switched to
| Python early/mid career. Teaching Python in undergrad
| _followed_.
|
| I also taught a mid-career Economics professor Python. She
| used SPSS before for her papers. Humanities professors
| doing data crunching are now switching to Python, too.
| There is a clear trend.
| taeric wrote:
| I argue that Python's success was almost entirely due to it
| not adopting any best practices on dependency management and
| being installed by default on systems.
|
| Being default installed was almost certainly the larger
| factor. As evidenced by how much pain it caused people when
| they started using dependencies that were not stable. They
| had to add specific support for it to not let you pip install
| things to the system install.
| runjake wrote:
| 1. Python was pretty popular well before entry-level
| programming courses adopted it. I think they adopted Python
| because it was a good general purpose scripting language,
| multiplatform, easy to install and get going, that taught
| programming concepts in a more approachable way for
| beginners.
|
| 2. Python on web servers was a thing _long before_ 2012. You
| had Zope in 1998 or so, and it was pretty popular for a
| while, and hugely influential to subsequent web frameworks.
| Django came out in about 2005. TurboGears, Pylons in about
| 2005 or so. Flask in 2010... and these are just the more
| popular frameworks.
|
| 3. I think the author meant that PHP was also vaguely C-like
| in syntax, like JS. Keyword: _vaguely_. You had a common way
| of declaring stuff with curly braces and semi-colons.
| dragonwriter wrote:
| > Python's success is entirely due to entry-level programming
| courses.
|
| No, entry-level courses were in a mix of Scheme, C, and other
| languages until Java's industrial ubiquity ended up in it
| becoming a popular choice, but not completely displacing the
| others. Then as Python (along with the broader class of
| dynamic OO scripting languages) became quite popular, Python
| got added to the mix, but, unlike Java, it fairly quickly
| displaced not only Java but a lot of what had been around
| longer in introductory courses.
|
| Python's industrial success drove its initial use in
| introductory courses, but doesn't fully explain it, as it
| doing what Java never did indicates.
|
| I think the people teaching introductory courses find it less
| of a compromise to industrial popularity than they did with
| Java.
|
| Python's success is multifaceted, some of it is right-place
| right-time, a lot of it is the ecosystem it built because of
| that, but a lot of it is, I think, that it turns out to be a
| language that has been designed (both initially and in how it
| is been managed over time) to be a very good language for
| real people solving real problems, despite not adhering to
| any of what various typing and performance and paradigm
| purists like to posit as the essential features of a good
| language.
| adw wrote:
| Peak PHP was Facebook around 2008!
| JodieBenitez wrote:
| > I don't think I heard about web servers in Python before
| 2012
|
| Excuse me but... what ? Django is 20 years old.
| alexjplant wrote:
| > They all switched to Python, because you have to explain
| less
|
| I think this could be generalized to ergonomics. Java 1.6 is
| an absolute nightmare for a newb compared to Python. No top-
| level statements, explicit typing, boxing, verbose
| declaration syntax, long import statements, curly braces
| everywhere... and, most importantly, no out-of-the-box REPL.
| Java has since made strides and borrowed from Kotlin and
| Lombok but my understanding is that it was too little too
| late.
|
| Depending upon preference and application one might consider
| ~half of these things anti-features at the expense of
| stability but it speaks volumes to why people join and stay
| in a software ecosystem. If I had to work on a Python project
| again I'd use mise with uv and viciously lint the codebase
| down to a reasonable fully-typed subset of the language
| devoid of custom decorator magic and dunder abuse.
| pron wrote:
| > but my understanding is that it was too little too late.
|
| Too little too late to be the #1 language of choice for
| serious server-side software that it is today?
|
| The weird thing about Java is that people naturally compare
| its popularity today to its dominance in the early '00s,
| which was an aberration. The ecosystem has long since
| returned to its fragmented self, and while Java is not
| nearly as dominant as it was during that very short period,
| no other language is, either.
| stevesimmons wrote:
| The key factor imo was Travis Oliphant merging the competing
| numeric and numarray libraries into numpy in 2005. That quickly
| became the foundation of Python as the key environment for open
| source numeric processing.
|
| It brought across a ton of users from R and Matlab.
|
| Pandas, Matplotlib and ScikitLearn then consolidated Python's
| place as the platform of choice for both academic and
| commercial ML.
| troad wrote:
| > According to programmers from 20 years ago, they were like
| religions. Each had its own philosophy and a loyal group of
| followers crusading online, getting into heated debates, all
| trying to win over more adopters.
|
| It's very weird reading something you lived through described
| in these terms, as though it were being described by an
| anthropologist.
|
| Can't help but wonder what the future will have to say about
| today.
|
| "In 2025, programmers used 'frameworks' to hang 'apps' from
| some kind of 'web'. They believed these frameworks gave them
| magic powers. Many even fought in 'flame wars' on this topic,
| which experts believe involved the use of fire to destroy webs
| woven by competing programmers."
| Twirrim wrote:
| > The 3 Ps made history. According to programmers from 20 years
| ago, they were like religions. Each had its own philosophy and
| a loyal group of followers crusading online, getting into
| heated debates, all trying to win over more adopters. The new
| generation of devs is more pragmatic. These days it's less
| about language wars and more about picking the right tool for
| the job.
|
| I feel like the religious wars aspects of this is completely
| overblown. The conversations around languages really hasn't
| changed all that much in the last 20 years. Look at the way you
| see things happening in HN, heck even in the comment thread
| right here. It's the exact same kinds of discussions as
| happened back 20 years ago, with exactly the same kind of
| pragmatism.
|
| I think the gulf comes about from the fact that the primary
| sources are conversations occurring between people that are
| largely anonymous behind an online handle, interacting with
| people that aren't face to face. There's always been an element
| of exaggeration in the interactions. What might be a "Umm, no"
| with a maybe a shake of the head, becomes "Your mother was a
| hamster and your father smells of elderberries". Almost every
| party involved comes to recognise the particular cultural
| quirks (which varied from forum to forum) and how to translate
| what was said, to what was actually meant.
| adw wrote:
| Python was everywhere in science by earlier than that (Numeric
| and numarray, Numpy's predecessors, are from the late 90s/early
| 2000s).
| spiderxxxx wrote:
| >From what I was told, Python was originally seen as a Swiss
| Army knife for sysadmins.
|
| Yea, I was a sysadmin around 2000 (before that too) and I knew
| it as such.
|
| >between 2005 and 2006, two important things happened:
|
| Somewhat - I used it in 2001 for Plone which is based on Zope,
| which was somewhat popular around that time. Writing all the
| web stuff with Python made sense, since Plone provided a CMS
| and could include a wiki. Adding on some sql calls to it in
| python just made sense. The competition was between PHP and
| Python, though there were some other less popular choices. Ruby
| on Rails definitely was getting a lot more popular around those
| times. PHP didn't start getting popular around 2005, if
| anything, people started using Python more, and started
| criticizing the crappy code that was circulating in the PHP
| community.
|
| In any case, it was a fun time, but what's the point of looking
| back like that?
| snapetom wrote:
| This aligns with what I remember and Guido going to Google
| explains things. Mid 2000's was all about PHP
| (Cake/Symphony/CodeIgniter/etc) vs Ruby (Rails) in the open
| source world. I remember hearing about Python only in sysadmin
| work and Plone. Then, suddenly were suddenly a lot of articles
| from Google about just about everything, all in Python.
|
| I remember saying to a coworker, "Google is single-handedly
| keeping Python alive."
|
| Then bam. It was everywhere. Mid 2010's, I took a cybersec job
| and they told me to learn Python in the two weeks between
| accepting and starting. "Python is all over cybersec," I was
| told. It was then I realized Python took over academia, which
| positioned it perfectly for ML. It's features made it easy to
| start, but it also benefited from right place, right time.
| t43562 wrote:
| I'm glad someone else discovered they can like python.
|
| I got forced to learn it for a project where I was proposing Ruby
| and the customer insisted on Python. This was years ago when Ruby
| was much slower. I was annoyed but I got used to it and here I am
| enjoying it many years later.
|
| I take issue with the description and use of make though! :-D
| What is the point of it if you're not going to use dependencies?
| One might as well just write a script with a case statement.....
| I'm adding smileys because I don't mean to be all that serious
| but I really do think that the failure of the youth of today to
| get to grips with Make is a sad reflection on our culture.......
| and get off my lawn, ok? :-)
| pphysch wrote:
| > One might as well just write a script with a case
| statement.....
|
| I started with this and evolved into simple flat Makefiles,
| because they're basically the same but Make feels more standard
| (there's a Makefile here vs. there's a random bash script
| here).
| DataDaoDe wrote:
| Python has done an impressive job over the years of making steady
| robust improvements. The typing and tooling has just gotten
| better and better. There are still plenty of problems though,
| imho async is still a much bigger pain than it should be
| (compared to other runtimes with a very nice experience like go
| or elixir, even dotnet has been less pain in my experience).
| Overall I like python, but it mainly boils down to the robust
| libraries for things I do (ML, Data munching/analysis)
| dmz73 wrote:
| I don't know what I am doing wrong but nothing written in
| Python has ever worked for me. I download the .py repo from
| from github or wherever and try to run it - errors. I try to
| install missing libraries pip this and that - errors. I battle
| fixing endless error with dependencies and when the .py finally
| runs - errors - wrong version of whatever library or wrong
| patch of this or that or the "production ready" .py does not
| work correctly on Windows or single file script uses excel
| library that has changed in incompatible ways 3 times in 2
| years. I Download all the files from the flashy looking web
| site and follow all the instructions to the letter - errors.
| Python is anything but "robust". It is the most fragile
| environment in the universe, worse than c, c++ and javascript
| put togeter, at least this is my experience with it.
| vrighter wrote:
| This is exactly my experience too. I avoid python software
| like the plague, because even when it does work, I can not
| rely on it continuing to work when python gets updated on my
| system.
| zeppelin101 wrote:
| This is where uv comes in to save the day.
| DataDaoDe wrote:
| That's wild. The last time I had that experience with Python
| must have been more than 10 years ago. I'll admit a decade
| ago you definitely did need to know way to many details about
| way too many tools from virtualenvs to setuotools to wheels,
| etc. to get things working from somebody else's project, but
| imho, poetry and uv have really changed all that.
| ActorNightly wrote:
| can you give at least one example? You are probably just
| expecting too much. No manual checkout/install process is
| easy as installing an application.
| jbreckmckye wrote:
| What about Go?
|
| "go install github.com/org/repo/x"
| dkdcio wrote:
| `pip install git+https://github.com/org/repo/x`
| latexr wrote:
| > I started to code more in Python around 6 months ago. Why?
| Because of AI, obviously. It's clear (to me) that big money
| opportunities are all over AI these days.
|
| I find this depressing. Not only are LLMs covertly reducing our
| ability to think and make decisions, they're now also making
| people voluntarily conform to some lower common denominator.
|
| It's like humanity decided to stagnate at this one point in time
| (and what a bad choice of point it was) and stop exploring other
| directions. Only what the LLM vomits is valid.
| mrpopo999999 wrote:
| humanity tried to save time and allocate it to other pursuits,
| don't worry
| taosx wrote:
| Unpopular opinion: I think I'm going to wait for version 4 /jk.
| But honestly, I've been spoiled by modern languages like Rust,
| Go, and even TypeScript with modern tooling, strong typing,
| stability, and performance out of the box. Right now, I'm just
| interacting with LLMs, not building them.
|
| That said, I remember writing myself a note a few years ago to
| avoid Python projects. I had to clean up code from all over the
| company and make it ready for production. Everyone had their own
| Python version, dependencies missing from requirements.txt, three
| way conflicts between 2 dependencies and the python version,
| wildly different styles, and a habit of pulling in as many
| libraries as possible [1]. Even recalling those memories makes my
| stomach turn.
|
| I believe constraints make a project shine and be maintainable.
| I'd prefer if you throw at me a real python instead of a python
| project.
|
| [1] Yes, I'm aware of containers, I was the unlucky guy writing
| them.
| bigiain wrote:
| > Unpopular opinion: I think I'm going to wait for version 4
|
| In my personal timeline, people giving up waiting for Perl 6
| were a huge source of early Python developers.
| 1ncunabula wrote:
| What makes TypeScript better than Python? I don't get it..
| Philpax wrote:
| Much more capable and reliable type system, paired with
| comparatively sane package management. This is getting better
| in the Python world (thank you Astral), but it's still not
| anywhere near the same.
| theLiminator wrote:
| I don't have a strong love for python, but all the tooling the
| author mentioned has actually made python fairly decent to use
| now.
|
| Still could be better, but I think Python's really hit its
| stride now.
| Surac wrote:
| have fun!
| CoolCold wrote:
| > Not only because the syntax is more human-friendly, but also
| because the Python interpreter is natively integrated in all Unix
| distros
|
| That's kind of very optimistic evaluation - literally anything
| beyond "import json" will likely lead you into the abyss of
| virtual envs. Running something created with say Python 3.13.x on
| Ubuntu 22.04 or even 24.04 (LTSs) / Rocky 9 and the whole can of
| worms opened.
|
| things like virtual envs + containers (docker like)/version
| managers become a must quickly.
| nikisweeting wrote:
| this is solved by uv
| CoolCold wrote:
| > things like virtual envs
|
| I consider my point as still valid with UV, what you wanted
| to express?
|
| On UV specifically - say 'asdf' compiles python right on your
| system from official sources - means using your ssl libs for
| example. UV brings Python binary - I feel worried on this.
| charliermarsh wrote:
| uv works just as well with whatever Python you want to
| bring -- you're not required to use the Pythons that uv is
| capable of installing on your machine.
| acdha wrote:
| "import json" is the kind of thing which requires picking and
| installing libraries in batteries-not-included languages, and
| it's just one of many modules which are in the standard
| library. That's not a compelling basis for large projects but
| over the years I've shipped a ton of useful production code
| which never needed more than the stdlib and thus spent no time
| at all thinking about deployment or security patching.
|
| Also, it's not the 2000s any more. Using venv to isolate
| application installs is not very hard anymore and there have
| been decent package managers for a long time.
| frollogaston wrote:
| The official package manager is pip, it's broken, and there
| has been a new "permanent solution" replacement for it each
| year.
| acdha wrote:
| "broken" is hyperbole. It works fine for millions of people
| every day. If you have some specific scenarios where you
| want it be better, it's better to say those rather than
| just complain about an open source project.
| frollogaston wrote:
| Millions of people put it into Docker, or they just deal
| with it and you see the results with tons of
| Stackoverflow questions
| BeetleB wrote:
| > Millions of people put it into Docker, or they just
| deal with it and you see the results with tons of
| Stackoverflow questions
|
| Arrogantly wrong.
|
| I've coded in Python for almost 20 years. Many of those
| years I've had it as my primary language at work.
|
| 2024 was the first year I actually _needed_ a virtualenv.
| Before that, I 'd happily use pip to install whatever I
| want, and never had a version conflict that caused
| problems.
|
| I often encounter junior folks who default to using a
| virtualenv, not because they _need_ to, but because they
| 've been brainwashed into believing that "you're doing it
| wrong if you don't use one".
|
| In any case, people should use uv these days.
| underdeserver wrote:
| Poetry has been decent for years. uv is new but great and
| will likely continue to be.
| icedchai wrote:
| uv is soooo much faster than Poetry, especially for
| dependency resolution.
| wpm wrote:
| I have a silly theory that I only half joke about that
| docker/containers wouldn't've ever taken off as fast as it did
| if it didn't solve the horrible python dependency hell so well.
| You know something is bad when fancy chrooting is the only
| ergonomic way of shipping something that works.
|
| My first taste of Python was as a sysadmin, back in 2012 or so,
| installing a service written in Python on a server. The
| dependency hell, the stupid venv commands, all this absolute
| pain just to get a goddamn webserver running, good lord. It
| turned me off of Python for over a decade. Almost any time I
| saw it I just turned and walked away, not interested, no
| thanks. The times I didn't, I walked right back into that pile
| of bullshit and remembered why I normally avoided it. The way
| `brew` handles it on macOS is also immensely frustrating,
| breaking basic pip install commands, installing libraries as
| commands but in ways that make them not available to other
| python scripts, what a goddamn disaster.
|
| And no, I really have no clue what I'm talking about, because
| as someone starting out this has been so utterly stupid and
| bewildering that I just move on to more productive, pleasant
| work with a mental note of "maybe when Python gets their shit
| together I'll revisit it".
|
| However, uv _has_ , at least for my beginner and cynical eyes,
| swept away most of the bullshit for me. At least superficially,
| in the little toy projects I am starting to do in Python
| (precisely because its such a nicer experience), it sweeps away
| most of the horrid bullshit. `uv init`, `uv add`, `uv run`. And
| it just works*.
| stanleydrew wrote:
| > I have a silly theory that I only half joke about that
| docker/containers wouldn't've ever taken off as fast as it
| did if it didn't solve the horrible python dependency hell so
| well.
|
| I don't think this is a silly theory at all. The only
| possibly silly part is that containers specifically helped
| solve this problem just for python. Lots of other software
| systems built with other languages have "dependency hell."
| asa400 wrote:
| > However, uv has, at least for my beginner and cynical eyes,
| swept away most of the bullshit for me.
|
| uv is _much_ better than what came before. As someone who has
| only had only glancing contact with Python throughout my
| career (terrible experiences at jobs with conda and pip), uv
| feels like Python trying to actually join the 21st century of
| package management. It's telling that it's in Rust and
| clearly takes inspiration from Cargo, which itself took
| inspiration from Ruby and Bundler.
| paradox460 wrote:
| The funniest thing for me is that you can use uv in mise to
| install Python cli programs in a surprisingly elegant
| manner.
| Ringz wrote:
| Just curious: how?
| asa400 wrote:
| They may be referring to uvx:
| https://docs.astral.sh/uv/guides/tools/
|
| Or it could be something else, not sure.
| macawfish wrote:
| `uv tool install` I believe
| frollogaston wrote:
| Yeah, if you look at a big Python vs Node vs Rust repo side
| by side, you'll notice Python is often the only one with a
| Dockerfile.
| 762236 wrote:
| I won't touch Python either, but because I've been burned
| debugging large Python programs. Something that would have
| taken a minute in a statically typed language took hours of
| tracing data through the program to understand what was
| supposed to be in a dict. There are alternative languages
| that are pithy, statically typed, can write programs quickly,
| and can grow into large code bases that are maintainable; so
| there is never a reason to start a new project with Python
| today.
| turtlebits wrote:
| You should always use virtual envs. They're a single directory,
| how are they an abyss? Pip now complains if you try to install
| a package system wide.
| unethical_ban wrote:
| For shadow IT, anything that requires "installation" vs.
| being in the base system or being added as a file to a
| project is an inconvenience.
|
| It's why I like using Bottle for small Python frontends:
| download the file and import.
|
| (I'm ranting based on personal experiences with IT in the
| past. Yes in general virtualenv is the baseline)
| ActorNightly wrote:
| Compile python to executable is always an option.
| shakna wrote:
| If you're dealing with a managed system, chances are,
| compilers are banned. You'll have to be unsafe and work
| outside the constrained environment - potentially
| violating policies, contracts, regulations and laws.
| nomel wrote:
| > You should always use virtual envs.
|
| If you're not using dependencies, and are writing 3.x code,
| there's very little justification.
| frollogaston wrote:
| I don't have to deal with this in JS or I think in other
| stuff like Golang. I give someone a package.json with
| versions of everything. npm install always sets deps up
| locally, but doesn't need to copy the entire NodeJS runtime.
| deathanatos wrote:
| ... node_modules is your venv.
|
| If we use uv from TFA, like the commands are nearly 1:1:
| npm install <=> uv sync npm install foo <=> uv
| add foo
|
| > _It doesn 't have to also store a local copy of NodeJS_
|
| ... which Node devs _do_ have a thing for, too, called nvm,
| _written in bash_.
| frollogaston wrote:
| The difference is it's default, it always works the same
| everywhere, it actually writes down the deps, and I don't
| have to manually switch between them (or set up fancy
| bashrc triggers) like venvs.
| deathanatos wrote:
| > _it 's default_
|
| This point is true; the ecosystem simply can't change
| overnight. uv is getting there, I hope.
|
| > _it always works the same everywhere_
|
| `uv` works the same, everywhere?
|
| > _it actually writes down the deps_
|
| `uv add` does that, too.
|
| > _I don 't have to manually switch between them (or set
| up fancy bashrc triggers) like venvs._
|
| You don't have to do that with `uv`, either?
| frollogaston wrote:
| That's great, I hope they make it default, then Python
| package management won't be broken anymore (for new
| projects at least, not all the legacy). Default has been
| pip for years, and there are tons of hard-to-build repos
| cause the author missed something in their manual
| requirements.txt gathering.
| ziml77 wrote:
| Yes, please use virtual envs or containers. I know it seems
| overly heavy and hard to manage, but you don't want to end up
| in a situation where you're afraid to update the system because
| the library upgrades might break some of your Python code.
| ActorNightly wrote:
| No and no. I don't know how you even get to this level of
| "making it harder for yourself".
|
| Say you want to use a specific version of python that is not
| available on Ubuntu.
|
| 1. Install build dependencies
| https://devguide.python.org/getting-started/setup-building/#...
|
| 2. Download whichever Python source version you want,
| https://www.python.org/downloads/source/. Extract it with tar
|
| 3. run ./configure --enable-optimizations --with-lto
|
| 4. run make -s -j [num cores]
|
| 5. sudo make altinstall
|
| This will install that specific version without overwriting
| default system python.
|
| You can then bash alias pip to python3.xx -m pip to make sure
| it runs the correct one.
|
| All the libraries and any pip install executable will be
| installed locally to ~/.local folder under the specific python
| version.
|
| Alternatively, if you work with other tools like node and want
| to manage different versions, you can use asdf, as it gives you
| per folder version selection.
|
| virtual environments are really only useful for production
| code, where you want to test with specific versions and lock
| those down.
| icedchai wrote:
| Personal preference, but I prefer to use 'mise' instead of
| 'asdf' these days: https://mise.jdx.dev/
| dragonwriter wrote:
| Virtual environments are useful for isolating dependencies
| for different projects, not just isolating the interpreter.
|
| (I mean, except on Windows, your venvs default to symlinking
| the interpreter and other shared bits, so you aren't really
| isolating the interpreter at all, _just_ the dependencies.)
| ElectricalUnion wrote:
| AFAIK, it's the same even on POSIX, when you create a venv,
| "./bin/python" are symlinks and the pyvenv.cfg has a
| hardcoded absolute path of the current python interpreter
| the venv module was using at the time of creation. It
| really doesn't isolate the interpreter.
|
| (also one of the reasons why, if you're invoking venv
| manually, you absolutely need to invoke it from the correct
| python as a module (`python3.13 -m venv`) to make sure
| you're actually picking the "correct python" for the venv)
| dragonwriter wrote:
| I meant that the symlink behavior is default except on
| Windows (though it may just be on POSIX platforms and I
| think of it as "except Windows" because I don't
| personally encounter Python on non-Windows non-POSIX
| platforms.)
| MintPaw wrote:
| > making it harder for yourself
|
| Looking at just the first link, looks way more complicated
| than venv. And I'm a C++ developer, imagine someone who less
| experienced, or even who just isn't familiar with C
| toolchains.
| ActorNightly wrote:
| The first link is a sudo apt install command that you copy
| paste into terminal. in what world is that more complicated
| than venv?
|
| Here it is for clarity
|
| sudo apt-get install build-essential gdb lcov pkg-config \
| libbz2-dev libffi-dev libgdbm-dev libgdbm-compat-dev
| liblzma-dev \ libncurses5-dev libreadline6-dev
| libsqlite3-dev libssl-dev \ lzma lzma-dev tk-dev uuid-dev
| zlib1g-dev libmpdec-dev libzstd-dev
| sevensor wrote:
| It's really not hard; the person you're replying to put a
| lot of details in. I've lost track of how many times I've
| built a Python interpreter. Virtual envs used to work badly
| with some tools and dependencies, so I had to do it a lot.
| It's gotten better and now I only compile Python to get a
| version that's not provided by my Linux distribution.
| frollogaston wrote:
| Also in some older cases the pre-included Python is v2 and the
| system relies on it, which is more of a liability.
| geysersam wrote:
| Just use uv
| igor47 wrote:
| Good write up, and solid choices. As someone primarily working in
| python in the last few years, I have a very similar stack.
|
| Two additional suggestions:
|
| * mise to manage system dependencies, including uv version and
| python itself
|
| * just instead of make; makefile syntax is just too annoying.
|
| Mise actually has a command runner as well which I haven't tried
| yet, and might work better for running commands in the context of
| the current environment. It's pretty nice when your GitHub
| actions workflow is just:
|
| * Install mise
|
| * mise install everything else
| elemcontrib wrote:
| I don't see how the OP layering utilities on top of python
| remediates on the claim that the language is not "production
| ready". Which it clearly is.
| flyinghamster wrote:
| I've avoided Python for a long time, but I'm getting roped in
| myself, mainly because certain tasks seem to require a lot less
| code than Java or Perl.
|
| That said, call me old-fashioned, but I really take issue with
| "curl $URL | bash" as an installation method. If you're going to
| use an install script, inspect it first.
| limagnolia wrote:
| If your going to execute the code anyway, you either have to
| inspect everything or trust whoever is providing it. There is
| nothing special about bash that makes it more dangerous to
| execute than python.
| drdrey wrote:
| do you also inspect binary installers?
| Mawr wrote:
| Just a small note on the code in the linked script:
| API_KEY = os.environ.get("YOUTUBE_API_KEY") CHANNEL_ID =
| os.environ.get("YOUTUBE_CHANNEL_ID") if not
| API_KEY or not CHANNEL_ID: print("Missing
| YOUTUBE_API_KEY or YOUTUBE_CHANNEL_ID.") exit(1)
|
| Presenting the user with "Missing X OR Y" when there's no reason
| that OR has to be there massively frustrates the user for the
| near zero benefit of having one fewer if statement.
| if not API_KEY: print("Missing YOUTUBE_API_KEY.")
| exit(1) if not CHANNEL_ID: print("Missing
| YOUTUBE_CHANNEL_ID.") exit(1)
|
| Way better user experience, 0.00001% slower dev time.
| niux wrote:
| Why not add a boolean flag and use a single exit(1) at the end?
| That way the user can see all the environment variables that
| have not been set.
| gvalkov wrote:
| This is nitpicking, but this is a good usecase for the :=
| operator: if not (API_KEY :=
| os.getenv("API_KEY")): ...
|
| For internal tools I just let os.environ["API_KEY"] raise a
| KeyError. It's descriptive enough.
| arthurcolle wrote:
| I always forget this syntax exists. When was this introduced?
| gvalkov wrote:
| In Python 3.8 - https://peps.python.org/pep-0572/
| DangitBobby wrote:
| October 2019 in Python 3.8
|
| https://docs.python.org/3/whatsnew/3.8.html
| cranium wrote:
| The Walrus operator! Introduced in Python 3.8 according to
| the PEP 572.
|
| Really nice to combine 1) checking if something exists and
| 2) act on it
| indymike wrote:
| You forgot to end with "goo goo g'joob" or the less
| correct Simon and Garfunkel version "coo coo ca choo".
| tyrust wrote:
| I write a decent amount of Python, but find the walrus
| operator unintuitive. It's a little funky that API_KEY is
| available outside of the `if`, perhaps because I had first
| seen the walrus operator in golang, which restricts the scope
| to the block.
| bobbylarrybobby wrote:
| This isn't really unique to the walrus operator, it's just
| a general python quirk (albeit one I find incredibly
| annoying). `for i in range(5): ...` will leave `i` bound to
| 4 after the loop.
| yread wrote:
| Maybe Python will get a let one day
| nomel wrote:
| Oddly enough, "except" variables don't remain bound!
| try: x = int('cat') except Exception
| as e: pass print(e) # <- NameError:
| name 'e' is not defined
|
| So, it appears Python actually has _three_ variable
| scopes (global, local, exception block)?
| agumonkey wrote:
| exceptions being the exception is funny somehow
| tough wrote:
| very recursive
| mananaysiempre wrote:
| Also true of JavaScript pre-ES5, another language that on
| first glance seems to only have function scope: it
| actually does have block scope, but only for variables
| introduced in `catch` blocks. AFAIU that was the standard
| way for a dumb transpiler to emulate `let`.
| SerpentJoe wrote:
| I wonder if that was ever popular, considering the
| deoptimization effects of try/catch, and given that block
| scope can also be managed by renaming variables.
| suspended_state wrote:
| > Oddly enough
|
| It's not that odd, since it's the only situation where
| you cannot keep it bounded, unless you enjoy having
| variables that may or may not be defined (Heisenberg
| variable?), depending on whether the exception has been
| raised or not?
|
| Compare with the if statement, where the variable in the
| expression being tested will necessarily be defined.
| NekkoDroid wrote:
| While somewhat true, what would this be bound to?
| for i in range(0): pass
| suspended_state wrote:
| Well, after writing my comment, I realized that a python
| interpreter could define the variable and set it to None
| between the guarded block and the except block, and
| implicitly assign it to the raised exception right before
| evaluating the except block, when the exception as been
| raised. So technically, it would be possible to define
| the variable e in GP example and have it scoped to
| "whatever is after the guarded block", just like what is
| done with for blocks.
|
| Is there any chance this would cause trouble though?
| Furthermore, what would be the need of having this
| variable accessible after the except block? In the case
| of a for block, it could be interesting to know at which
| point the for block was "passed".
|
| So, maybe "None" answers your question?
| MyOutfitIsVague wrote:
| > Compare with the if statement, where the variable in
| the expression being tested will necessarily be defined.
| if False: x = 7 print(x)
| print(x) ^ NameError: name 'x' is
| not defined
|
| Ruby does this sort of stuff, where a variable is defined
| more or less lexically (nil by default). Python doesn't
| do this. You can have local variables that only maybe
| exist in Python.
| MyOutfitIsVague wrote:
| Nope, it's more complicated than that:
| e = 'before' try: x = int('cat')
| except Exception as e: e2 = e
| print(e) print(e2) # <- This works!
| print(e) # <- NameError: name 'e' is not defined
|
| It's not a scoping thing, the bound exception variable is
| actually deleted after the exception block, even if it
| was already bound before!
| rolandog wrote:
| I may be rusty, but wasn't there a "finally" scope for
| those situations?
|
| edit: writing from phone on couch and the laptop... looks
| far, far away...
| tyrust wrote:
| Oh yeah, that's a good point.
|
| Python really is a bit of a mess haha.
| dec0dedab0de wrote:
| I find it incredibly intuitive and useful that it does
| that. sometimes it drives me nuts that it doesn't do it
| for comprehensions but I can see why.
|
| But if something fails in a loop running in the repl or
| jupyter I already have access to the variables.
|
| If I want to do something with a loop of data that is
| roughly the same shape, I already have access to one of
| the the items at the end.
|
| Short circuiting/breaking out of a loop early doesn't
| require an extra assignment.
|
| I really can't see the downside.
| bobbylarrybobby wrote:
| Python 2 actually did let comprehension variables leak
| out into the surrounding scope. They changed it for
| Python 3, presumably because it was too surprising to
| overwrite an existing variable with a comprehension
| variable.
| pletnes wrote:
| It would be utterly nuts otherwise. For loops over all
| elements in a sequence. If the sequence is a list of str,
| as an example, what would the <<item after the last
| item>> be?
| setr wrote:
| the issue isn't the value of i, the issue is that i is
| still available after the loop ends. in most other
| languages, if it was instantiated by the for-each loop,
| it'd die with the for-each loop
| all2 wrote:
| I cannot tell you how many times I've hit issues
| debugging and it was something like this. "You should
| know better" -- I know, I know, but I still snag on this
| occasionally.
| slightwinder wrote:
| This is just Pythons scoping, which is not restricted by
| block, but function. You have the same effect with every
| other element.
| MyOutfitIsVague wrote:
| There's no block scope in Python. The smallest scope is
| function. Comprehension variables don't leak out, though,
| which causes some weird situations: >>> s
| = "abc" >>> [x:=y for y in s] ['a', 'b',
| 'c'] >>> x 'c'
| >>> y Traceback (most recent call last):
| File "<stdin>", line 1, in <module> NameError: name
| 'y' is not defined
|
| Comprehensions have their own local scope for their local
| variables, but the walrus operator reaches up to the
| innermost "assignable" scope.
| lucb1e wrote:
| Why would you use it though? I always thought it a bad thing
| that legacy code (such as in C or C++) had these side effects
| inside of checks happening
| make3 wrote:
| no one uses walrus
| wcrossbow wrote:
| Even better is to try to fetch all the env variables and then
| report on all of the missing ones.
| pyuser583 wrote:
| It would be better to do both: print out the detailed string or
| strings, then exit if either are printed.
| danielrico wrote:
| Even better, check all the conditions and report all the
| errors. Don't make me add the first variable, run it again and
| get another error.
|
| Sometimes that's inevitable, bit noisy of the time it isn't.
| taeric wrote:
| I'm surprised there isn't an argparse like thing for
| documenting expected environment variables.
| paisawalla wrote:
| Taking ephemeral arguments like channel ID from the environment
| is more offensive to observability and user comfort
| conductr wrote:
| I feel like use case and audience matters when making these
| decisions. In this case, the user is probably someone
| interacting with a python script they're running in a console
| (I assume by print), then I really don't think it matters - the
| user will check that both things are set. Should you also give
| them some documentation about setting env vars? Should you
| customize that documentation to the OS they're running? etc.
|
| If the user is a typical consumer using a typical consumer
| interface, then yes you want to handhold them a bit more.
| bjourne wrote:
| Neophytes take notice. Attention to details like this is what
| separates truly great programmers from merely good ones. That
| said, for scripts reusable by others you should use command
| line arguments . Environment variables in lieu of command line
| arguments is a huge code smell.
| shakna wrote:
| You don't generally want API keys accidentally recorded into
| someone's bash history.
| RadiozRadioz wrote:
| For this example, don't just command line arguments. There's
| an API key there, you don't want an API key visible in your
| cmdline.
| bjourne wrote:
| Then how would you SET the API key in the first place? :)
| The argument doesn't make any sense at all.
| medstrom wrote:
| In some .profile or .envrc or what you'd call such a
| file, I suppose.
| JohnKemeny wrote:
| exit("Missing ...")
|
| This prints the message and exits with code 1.
| cristoperb wrote:
| Even slightly better is to first check both
| if not API_KEY and not CHANNEL_ID: print("Missing
| both YOUTUBE_API_KEY and YOUTUBE_CHANNEL_ID.")
| exit(1) if not API_KEY: print("Missing
| YOUTUBE_API_KEY.") exit(1) if not
| CHANNEL_ID: print("Missing YOUTUBE_CHANNEL_ID.")
| exit(1)
|
| That way you don't end up fixing one just come back and be told
| you're also missing another requirement
| delusional wrote:
| Even better would be to only check each once and buffer the
| decision: valid = True if not
| API_KEY: print("Missing YOUTUBE_API_KEY.")
| valid = False if not CHANNEL_ID:
| print("Missing YOUTUBE_CHANNEL_ID.") valid =
| False if not valid: exit(1)
|
| This way you only check each value once (because your logic
| might be more complicated than just checking it's not set,
| maybe it can be wrongly formatted) and you still get to do
| whatever logic you want. It also removed the combinatorial
| problems.
|
| This is a pretty general principle of separating decision
| from action.
| make3 wrote:
| why print then exit(1) instead of raising an exception?
| firecall wrote:
| "I started to code more in Python around 6 months ago. Why?
| Because of AI, obviously. It's clear (to me) that big money
| opportunities are all over AI these days. And guess what's the de
| facto programming language for AI? Yep, that sneaky one."
|
| Why is that?
|
| Why Python for AI?
| johnisgood wrote:
| Possibly because many available LLMs run your Python code in a
| sandbox, which means less friction for vibe coders, or it may
| be a contributing factor at the very least.
| AlexeyBrin wrote:
| > Because many available LLMs run your Python code in a
| sandbox, which means less friction for vibe coders.
|
| This is false, a lot of non "vibe coders" are using Python
| for AI because of PyTorch and a many other AI libraries have
| first class Python support.
| johnisgood wrote:
| How do you know that it is not the reason or not ONE of the
| reasons? Seems pretty reasonable to me to use ChatGPT,
| Claude, or whichever one supports it.
|
| I am pretty sure some people (maybe this individual, too)
| may be using Python because their scripts can be executed
| in a sandbox on one of these websites.
|
| Heck, if it was as good at Factor or Forth as it is at
| Python, I would be writing more of them, too.
|
| In any case, you cannot claim that it is not one of the
| reasons. Can you?
| AlexeyBrin wrote:
| I read your initial message, now edited, as this is THE
| reason. Of course it can be one of the reasons for which
| the author chose Python.
|
| Also the _vibe coding_ part gave me the impression that
| you were implying that people that use /chose Python for
| AI are all vibe coders which is again false. Sorry if I
| misunderstood you, but this is what I got from your
| initial message.
| johnisgood wrote:
| No worries. I think there was a misunderstanding because
| even with my original message, I did not intend to
| suggest that people who use or choose Python for AI are
| all vibe coders, or at least I didn't think I did hint at
| that.
| AlexeyBrin wrote:
| Because you get first class support in many AI libraries like
| PyTorch, TensorFlow and so on ... Most of these libraries can
| be used from other programming languages too, but it is easier
| to find good documentation and examples for Python.
| Hizonner wrote:
| I wonder what the poor guy is switching from.
| moribvndvs wrote:
| I don't understand "switching" to anything. The job picks the
| tool, not the other way around.
| Bridged7756 wrote:
| I think it's mostly boredom-driven career choices.
| 1vuio0pswjnm7 wrote:
| "And guess what's the de facto programming language for AI? Yep,
| that sneaky one."
|
| Is this referring at all to to PyTorch. If not, any guesses what
| the author has in mind
|
| "Not only because the syntax is more human-friendly, but also
| because the Python interpreter is natively integrated in all Unix
| distros."
|
| Is this referring to GNU/Linux.
|
| UNIX (UNIX-like) includes more than Linux; some UNIX
| distributions do not include Python in the base system
|
| Where it is left as choice to the user whether to install it
|
| I know this because I use such distributions and, unless some
| software needs it, I do not install Python
|
| In such case, when I am done using that software I uninstall it^1
|
| For example, he mentions retrieving YouTube channel metadata
|
| I do not use Python for this; I use a 19-line shell script (ash
| not bash), its startup time is faster
|
| Unlike Python, it is included in the base system of the UNIX
| distributions (both Linux and BSD) that I use
|
| But if I need to test something using yt-dlp, then I might
| temporarily install Python
|
| 1. I compile Python from source and one annoying aspect of the
| project , in addition to the slow startup time, is their failure
| to include an uninstall target in their Makefile
| megaloblasto wrote:
| "And guess what's the de facto programming language for AI?
| Yep, that sneaky one."
|
| He's referring to Python in general
|
| "Not only because the syntax is more human-friendly, but also
| because the Python interpreter is natively integrated in all
| Unix distros."
|
| I think he means that its available or readily available in
| many major linux distributions like Ubuntu, Fedora, NixOS, etc.
| I don't think native is the right word.
|
| I use bash too but Python is amazing. You're right, there are
| problems related to packaging and speed, but it is still very
| often the right tool for the job. It's powerful, easy to use,
| and open source.
| 1vuio0pswjnm7 wrote:
| "I use bash too but Python is amazing."
|
| I do not use bash. I use ash. Bash is too slow for me, like
| Python.
| donkeybeer wrote:
| What is the reason you prefer not to simply let python lie
| around? Security?
| 1vuio0pswjnm7 wrote:
| Storage space usually. Even when I have surplus space I still
| like to have minimal userlands with only the utilities I am
| actually using.
| ic_fly2 wrote:
| pydantic basemodel has made dataclasses redundant.
| _Wintermute wrote:
| Dataclasses have the one massive benefit of not being an
| additional dependency.
| ddejohn wrote:
| This. You also don't really need Pydantic unless you're
| de/serializing data from external sources. A dataclass is
| perfectly cromulent if you're just passing around data
| internally.
| yomismoaqui wrote:
| Python is the 2nd best language at everything.
| nilamo wrote:
| And the first best is python3!
| runjake wrote:
| I really don't find the Python language elegant at all. I prefer
| the Ruby syntax.
|
| But Python's tooling, particularly with what Astral is doing (uv,
| ruff, ty), is so good, I'm always using Python and virtually
| never using Ruby. And yeah, the rich libraries, too.
| Arch-TK wrote:
| Ubiquitous VSCode - honestly a tragedy.
| Night_Thastus wrote:
| I love writing Python. However, there are caveats:
|
| 1: I don't like dealing with language crossing boundaries with it
| - it's painful, especially if to/from a compiled language -
| there's just too much friction. It's easy to _write_ but hard to
| _maintain_.
|
| 2: Debugging python can be...painful. If you have a pure perfect
| environment dedicated to pure python and all the tooling set up,
| it can be breezy. But if you have something messier like C++ that
| calls Python or vice-versa and are using an editor not made for
| Python like QTCreator then suddenly it becomes hell.
|
| Who owns this data!? Where was this initialized!? What calls this
| function!? What type is this data!?!?!?!? These questions are so
| effortless in C++ for me and so very painful in Python. It slows
| efforts to a crawl.
|
| It feels exhausting to have to go back to print statements, grep,
| and hand-drawing a graph that shows what functions call what just
| to figure out WTF went wrong. It's painful to a degree that I
| avoid it as much as possible.
|
| ...and don't even get me started on dealing with dependency
| problems in deployments...
| gh02t wrote:
| I've long lusted after a smooth debugging workflow writing
| Cython that would let you seamlessly debug between Python and
| C/C++. I think there are some hacks to do it, but nothing
| really well integrated.
| miguel_martin wrote:
| Python debugging is great when you're strictly debugging Python
| code. Placing a `breakpoint` or spinning up an IPython instance
| to investigate the issue via `import IPython; IPython.embed()`
| makes life breezy. For neovim, you can send code to the ipython
| REPL easily via vim-slime.
|
| I've never found myself debugging the underlying C++ code
| unless developing a C++ extension. But is it really that hard?
| Just point lldb to the python process and run your script in
| lldb.
|
| If the C++ is not yours & assuming it's a mature lib (e.g.
| PyTorch): it's probably an error caused by you in Python land.
| Night_Thastus wrote:
| Both the C++ and Python are mine. I have cases of both C++
| calling Python, and Python calling C++. Problems could be on
| either side.
|
| The problem is how to step into one from the other, you
| really can't as far as I know.
|
| The python parts aren't standalone enough that it could just
| be run on its own, there's so much setup involved prior to
| that point that it can really only be run from the top-level
| user controls.
| jlarocco wrote:
| When did Python go out of fashion? This is the second article
| I've seen talking about it as if it's some kind abomination.
|
| I get that it's not the shiny new thing, but I don't understand
| people hating on it. Is this just junior devs who never learned
| it, or is there some new language out that I missed? (And please
| don't tell me Javascript....)
| wk_end wrote:
| Yes, I'd say Python's crown as the go-to lightweight scripting
| and web development language was mostly ceded to JS.
|
| It's still reigning champion of data science, and of course it
| has a huge number of uses and users still around, but it's not
| really cool or in vogue outside of those circles.
| jraph wrote:
| Do people really turn to JS (instead of Python) for
| lightweight scripting? Are we talking about the "better Bash"
| use case?
| ajkjk wrote:
| that would be very surprising
| tempest_ wrote:
| JS devs do, and there are a lot of them
| roflchoppa wrote:
| I mean if its really light weight, and I want to avoid
| bash, then JS is not too bad. The downside being that the
| built-ins are not really there compared to Python.
|
| The famous answer.... _it depends_.
| mjr00 wrote:
| > It's still reigning champion of data science, and of course
| it has a huge number of uses and users still around, but it's
| not really cool or in vogue outside of those circles.
|
| This is a wild take. You're never going to get a fully
| accurate measurement but every source I've seen[0][1][2] puts
| Python as _the_ most common programming language by a country
| mile.
|
| If it doesn't seem "cool" or "in vogue", that's because
| everyone is already using it.
|
| [0] https://www.tiobe.com/tiobe-index/ [1]
| https://pypl.github.io/PYPL.html#google_vignette [2]
| https://www.pluralsight.com/resources/blog/upskilling/top-
| pr...
| slightwinder wrote:
| Python has never been THE web development language, that's
| always been JavaScript. Python is one of the more popular
| server-side languages, and JavaScript has move from frontend
| to backend in the last decade too. Not sure whether this has
| really taken the crown of any backend-language.
|
| And what is lightweight scripting? Isn't scripting by
| definition lightweight?
|
| But Python overall is still very popular outside the Data
| Science-circles. Not sure where this claim is coming from.
| ravenstine wrote:
| I personally dislike Python, but it does surprise me that
| anyone is acting like it's generally disliked because that has
| definitely _not_ been my impression since time immemorial. I
| doubt that it 's gone out of fashion. More likely, acting like
| something actually doesn't suck after all has become the
| clickbait framework du jour.
| vinceguidry wrote:
| There are massive numbers of devs who would never even think of
| trying to code in a dynamically-typed language, even though the
| big players all have gradual typing. They don't know what
| they're missing.
| leptons wrote:
| I have no problem with dynamically-typed languages, my main
| problem with Python is the significant whitespace. _I really
| do not like it._ I can deal with everything else in Python,
| or any other programming language, but significant whitespace
| is what kills it for me.
| biztos wrote:
| Having gotten back into Python for a project after some
| time away, I found the solution (for me) is to
| automatically fix the whitespace every time I run the code.
|
| I just have a line in my Justfile that does this. Probably
| would be better to format on save but I use different
| editors and haven't gotten around to it.
|
| Still doesn't fix the creeping doubts about _everything_ in
| a language conceived by people who made that whitespace
| call, but it removes the specific pain point.
| yoz-y wrote:
| Even after writing tons of python the whitespace is still
| the reason why I never reach for it by default.
|
| Today the IDEs got much better, but I still can't see the
| significant whitespace as anything than downside. With
| brackets I can indent, but also have automatic indenting
| succeed every single time.
| daedrdev wrote:
| do you mean requirement of whitespace or how much space
| that takes up? Because you can change how many spaces
| python needs for its indentation to get some reduction in
| whitespace
| leptons wrote:
| I've been writing code for 40+ years. I know how to set
| up my editor, thanks.
|
| If you copy and paste some Python code and it isn't
| indented properly, it breaks the python program. It's the
| stupidest thing I've seen in any language, including
| javascript (which isn't as stupid as many claim it is).
| guhcampos wrote:
| Apparently the author used to be a Java person. I have this
| feeling - or prejudice - that people still in the Java World
| are a bit out of tune with the tech industry, working on huge
| legacy projects on big retail or US banking. These people tend
| to be conservative and resistant to change, so maybe that's
| where these types of articles are coming from.
| tombert wrote:
| I gave a talk recently at a conference about how modern Java
| doesn't suck very much, and that the worst part of Java is
| Java developers, who seem to be completely intellectually
| unambitious.
|
| I don't think Java makes anyone unambitious, I think it's
| that Java is taught in schools and unambitious people don't
| feel the need to learn anything else, and they get jobs at
| unambitious corporations. It selection-biases towards
| unambitious people who don't want to learn more than they
| have to.
|
| Compare this to something like Clojure or Haskell or
| something, which isn't routinely taught at schools and is not
| very employable. People who learn these languages generally
| _seek out_ these things because they're interested in it.
| This selection-biases towards intellectually ambitious
| people.
|
| As a result, Java people can be insufferable for people like
| me.
|
| The people who _make_ Java have actually made the platform
| and language pretty ok in the last two decades, but I had to
| fight at a previous job to use _NIO_ , which I think was
| introduced in Java 4, but none of my coworkers had really
| heard of it or used it because the regular Java blocking IO
| has been "good enough".
| dzonga wrote:
| link to talk please if recorded.
|
| I think one comment I saw here on HN that Java is better if
| written in Pythonic way. I agree completely with that
| stance.
|
| but yeah within Java you've 'merchants of complexity'
| people who wanna do things in the most abstract way rather
| than the simple way.
|
| btw Java can be as simple as Go.
| tombert wrote:
| I don't think that the talk has been released on public
| YouTube yet (and they made it clear to not share the
| unlisted links publicly), but here is the posting:
| https://www.lambdadays.org/lambdadays2025/thomas-gebert
|
| And the slides are available here: https://github.com/Tom
| bert/lambda_days_2025/blob/main/slides...
|
| I'm afraid that my humor isn't really reflected in the
| slides, but imagine everything here is said kind of
| snarkily.
|
| Java can be mostly as nice as Go, the BlockingQueues and
| Virtual Threads can get you pretty far, though they're
| not quite as nice as Go channels because there's no real
| way to select across multiple BlockingQueues like you can
| with Go channels.
|
| Overall though, I think Java 21 is actually not too bad.
| Shockingly, I even sometimes have fun writing it.
| _dain_ wrote:
| Github link is 404
| tombert wrote:
| Oops! Forgot to make the repo public!
|
| Should be fixed now. Sorry about that.
| ActorNightly wrote:
| >how modern Java doesn't suck very much,
|
| Given fact that Lombok is still pretty much widely used,
| with its under the hood functionality of essentially
| hacking the AST, or the fact that annotation processors
| write out Java code to files, or the fact that you could be
| using a standard library like Log4j and have a massive
| vulnerability on your system because someone decided that
| it would be a good idea if log statements could execute
| code and nobody said anything otherwise, or the fact that
| Kotlin and Groovy were literally made to address
| inefficiencies in Java, amongst other things....
|
| Yeah not really sure how you came to that conclusion.
| tombert wrote:
| That gets to my point though. For example, Lombok isn't
| really _necessary_ for a lot of stuff now, because
| Records give you a lot of what you would use with Lombok.
|
| Kotlin and Groovy did come and address problems with
| Java, you should use use them if your employer allows it.
| I'm just saying that Java 21 is actually kind of fun to
| write.
|
| Yes, some of the libraries have been unsafe, but that's
| one example of the 30 years of Java.
|
| I just feel like Java _has_ improved in the last twenty
| years. It 's the engineers that haven't.
| munificent wrote:
| I have a related feeling or prejudice that people not in the
| Java World view their corner as "the tech industry" without
| realizing that they are living in a village compared to the
| giant metropolis that is the Java World.
|
| Java programmers may not blog as much, and Java doesn't show
| up on Hacker News as much, but not being Extremely Online
| does not mean that it isn't extremely widely used by real
| people whose experiences are just as valid.
| bunderbunder wrote:
| If the TIOBE index is an even remotely useful indicator,
| Python's an even bigger giant metropolis.
| dietr1ch wrote:
| I'm not sure if they refer to how large the language's
| reach is, but more about how advanced Java is once you
| stop looking at syntax bloat. The JVM can do stuff that's
| not easy to do in other environments.
|
| I recall things like updating packages/code on the fly,
| recompiling fast paths on the fly. Maybe that's not
| necessary in a borg/kubernetes world where you can just
| restart things and have your load balancer infra take
| care, or just run slower code because compute isn't that
| expensive once you accelerate your CPU-heavy libraries,
| but cool anyways.
| munificent wrote:
| Yes, but the difference here is that Python is talked
| about all the time, so the online tech world _knows_ that
| Python is huge.
|
| The comment I was replying to seems to believe Java is a
| tiny backwater, which is anything but true.
| bunderbunder wrote:
| I read it less as "Java is tiny" and more as "Java
| developers can be peculiarly insular and conservative, by
| the standards of other communities."
|
| Considering that as recently as 4 years ago I was working
| on a project where we still had a hard requirement to
| support running in Java 7, and this kind of thing was not
| considered unusual, I can't really disagree too strongly
| with that. Yes, that was still inside of Java 7's
| extended support period, so there was really nothing
| unusual or surprising about this, from a Java developer
| perspective. But that's kind of the point.
|
| It's also not really a bad thing, considering what kinds
| of things run on Java. Mainframe developers have a
| similar thing going on, for a similar and similarly good
| reason.
| trchek wrote:
| You may know all this and are just singling out the Hacker
| News crowd. But I read your comment and thought "surely he
| doesn't think Java is much bigger than Python?" I'm not
| even sort of sure Python is smaller.
|
| Edit more succinct
| dec0dedab0de wrote:
| you could say the same thing about a dozen other languages,
| but there is definitely a stereotypical cranky java dev
| that is frustrated writing corporate crud apps that should
| in theory be blazingly fast, but never quite are for
| reasons. They revel in the verbosity, and look down on
| anyone they feel is taking the easy path. If you've never
| met one you're lucky, but they've been at every company I
| ever worked for.
| munificent wrote:
| _> you could say the same thing about a dozen other
| languages_
|
| No, you could not. You could say it about maybe four
| others: PHP, C, C++, and C#.
|
| No other languages have anywhere near the userbase size
| while being fairly quiet when it comes to online tech
| discussion.
|
| I agree there are crusty old Java devs (as well as crusty
| old C, C++, PHP, etc. devs). In a decade or two, there
| will be crusty old TypeScript devs. It's just the nature
| of technology lifecycles and career paths. Some people
| get relatively tired of learning when they get older and
| just want to capitalize on what they already know for
| their remaining earning years.
| PeterStuer wrote:
| I worked in .Net land before switching to Pythonville. It's
| very much like Java metropolis, but with less CS graduates.
| camcil wrote:
| Lest we forget that Python is ~4 years older than Java.
| supriyo-biswas wrote:
| This is absolutely correct as someone who has worked in a
| few Java shops. Although, the same thing is Java's failing,
| as it is well nigh impossible for people external to the
| Java ecosystem to learn what's inside it without having
| work-related exposure.
| ActorNightly wrote:
| The reason that people still code in Java (or derivative)
| is because legacy code that they are working on is in Java,
| and nobody has either the skill or time to go through and
| translate it. Which means that the jobs where its used are
| basically just big enterprise, low tech software that just
| been around for a while.
|
| The Log4shell incident is the perfect demonstrator of what
| kind of people are in Java world.
| munificent wrote:
| _> nobody has either the skill or time to go through and
| translate it._
|
| To what? Java is still a very efficient, productive
| language. Updating a legacy codebase to use newer Java
| features would probably be good, but migrating to another
| language is unlikely to significantly move the needle in
| terms of runtime performance or developer velocity.
| bunderbunder wrote:
| Java shops are certainly where I've witnessed the most
| disdain for Python. IME the strongest feelings tend to come
| from people who didn't actually have any significant
| experience with Python, and perhaps don't even have much
| practical experience with any language that isn't Java. So
| they tended to consider it to be objectively inferior purely
| because it's interpreted and dynamically typed.
|
| At a previous job I did manage to put a chip in that when I
| demonstrated replacing one of our Java services with a Python
| implementation. It was a fraction of the code, and achieved
| much better latency and throughput. Obviously not every
| Python program is going to do that. But my point isn't that
| Python is better, it's that these kinds of things are never
| so cut-and-dried. Many non-trivial Python programs are just
| thin shells around a large core of very well-optimized and
| battle-tested C/C++/Rust code. And Java, for its part, can
| also accumulate a lot of dynamic language-style performance
| losses to pointer chasing and run-time type lookups (and GC
| churn) if you're not careful about how you use generics. As
| always, the devil's in the details. It's also less able to
| pull the "actually I'm a C++" trick because using a
| compacting garbage collector makes it difficult to interop
| with native code without paying a hefty marshaling tax.
| deepsun wrote:
| I have way more experience with Python than Java. In at
| least 4 companies (including Google that I wouldn't call a
| javashop) we used mainly Python.
|
| Still I believe Java is a better application language.
| Python is a better scripting language (replacement for
| Bash). Small apps tend to be easier on Python, but large
| apps are way easier on Java, both for syntax (types) and
| ecosystem (libs).
| mey wrote:
| That is general take as well. A lot of small
| apps/simulators are in python. Ops scripts tend to be
| python. Java for the core/data. Refactoring/tooling is
| easier in Java when you are dealing with a 100k codebase
| imo. Typescript always.
|
| Seen plenty of coding horrors in both ecosystems...
| zeroc8 wrote:
| Algorithms are a lot easier to understand when they are
| written in Python. I'm actually right now documenting
| medium size Java codebase by writing pseudocode, which
| looks like Python. Just by doing that, I've already
| discovered multiple bugs, which I didn't catch by looking
| at the Java code.
| bunderbunder wrote:
| That might be the big thing that I think gets glossed
| over in a lot of these discussions. I agree that I
| wouldn't want to maintain 100kloc of Python. But, I don't
| really view that as a realistic hypothetical for a
| business application. Idiomatic Python tends to require a
| fraction as much code as idiomatic Java to accomplish the
| same task. The only time it even gets close is when you
| have code written by people who go out of their way to
| make things look like old-school enterprisey Java. So it
| ends up accumulating a bunch of stuff like
| class IWantToBeABean: def init(self, arg1: int,
| arg2: str, arg4: str) -> None: self._field1:
| int = arg1 self._field2: str = arg2
| self._field3: str = arg3 def
| get_field1(self) -> int: return self._field1
| def set_field1(self, value: int) -> None:
| self._field1 = value def
| get_field2(self) -> str: return self._field2
| def set_field2(self, value: str) -> None:
| self._field2 = value def get_field3(self) ->
| str: return self._field3 def
| set_field3(self, value: str) -> None:
| self._field3 = value
|
| when it could have just been: @dataclass
| class IDontWantToBeABean: field1: int
| field2: str field3: str
|
| The worse case for Python is when you get people doing
| the oldschool Python thing of acting like dynamic and
| duck typing means it's OK to be a type anarchist. Scikit-
| learn's a good one to put on blast here, with the way
| that the type and structure of various functions' return
| values, or even the type and structure of data they can
| handle, can vary quite a bit depending on the function's
| arguments. And often in ways that are not clearly
| documented. Sometimes the rules even change without
| fanfare on minor version upgrades.
|
| The reason why large Python codebases are particularly
| scary isn't necessarily the size itself. It's that for a
| codebase to even get that large in the first place it's
| very likely to have been around so long that the
| probability of it having had at least one major
| contributor who likes to do cute tricks like this is
| close to 1. And I'd take overly verbose like the Java
| example above over that kind of thing any day.
| deepsun wrote:
| Try Kotlin then.
|
| I wouldn't call it a new language, for me it's just a
| syntactic sugar over Java, but for any problem you would
| google "how to do X in Java", not "how to do X in
| Kotlin".
|
| But there you can do way simpler syntax, like:
| 0..100 meters with -45..45 deg within 3 seconds
|
| Because "0..100 meters ..." is equivalent to
| "(0..100).meters(...)"
|
| (0..100) is a built-in IntRange type, that you can
| extend: data class MyDistanceRange(val
| meters: ClosedRange<Double>) val
| IntRange.meters: MyDistanceRange get() =
| MyDistanceRange(first.toDouble()..last.toDouble())
|
| and
| bunderbunder wrote:
| Mostly agreed, though I would add that I'm generally
| happier with Python as a default for reasonably sized
| services that don't have a lot of (non-numpy-friendly)
| compute load and therefore don't have a pressing need for
| multithreading. Which is a lot of what happens now that
| we're all trapped in the cloud. Like you say, small apps
| tend to be easier in Python.
| ecshafer wrote:
| > Java, for its part, can also accumulate a lot of dynamic
| language-style performance losses to pointer chasing and
| run-time type lookups (and GC churn) if you're not careful
| about how you use generics.
|
| The worst thing about Java is the average quality of Java
| programmer.The same could probably be said about Python.
| However I think that there are fewer Python programmers
| trying to write AbstractFactoryFactory than in Java. Java
| has a terrible culture of overly verbose, deep inheritance
| trees that make debugging and development worse, with worse
| performance.
| NomDePlum wrote:
| I've always felt X was far superior to Y, and don't get me
| started on Z or W.
| rs186 wrote:
| I think at least half of amazon.com and AWS run on Java.
| pea wrote:
| I feel like the opposite is also true. People view Java as
| enterprise Java from 2008; a clunky outdated language for
| bad, verbose spaghetti code.
|
| In fact, a lot of the most interesting plt and compiler r&d
| going into real world applications is on the jvm (project
| loom, graal etc), and the features of modern Java (pattern
| matching, records, etc) make it a great choice for lots of
| projects that aren't legacy enterprise apps.
| le-mark wrote:
| > I have this feeling - or prejudice - that people still in
| the Java World are a bit out of tune with the tech industry
|
| Other than being ageist, it's wrong; or misattributed to
| Java. I work with Python every day, and what's missing is
| static typing and IDEs that make use of it to greatly reduce
| the amount of code and context I have to store in my head.
| Python (a dynamically typed language obviously) is exhausting
| to maintain. But easy to write. Java/C#/whatever statically
| typed language with great IDE is easy to write and maintain
| by comparison.
|
| Of course there are IDE for Python and dynamically typed
| languages, but everyone I've tried has fallen short compared
| to the best Java/c# IDEs.
|
| Static vs dynamic used to be a huge flame war on the
| internet, but over the past few years I've encountered people
| who've never heard of it. This is it.
| callc wrote:
| I coded happily in python for many years and fell out of love
| with it.
|
| It doesn't ship with a first party package manager so you got
| the community trying to fill this gap. Use any other language
| with good tooling like golang or rust and it is a breath of
| fresh air.
|
| Python used as an actual PL is a footgun because it's dynamic
| scripted. (Don't tell me about using tools X, Y, Z, mypy, ...)
| You essentially become the compiler checking types, solving
| basic syntax errors when uncommon paths are executed.
|
| A programming language that's only good for < 100 line scripts
| is not a good choice.
|
| I honestly wish python were in a better state. I switched to
| rust.
| rsyring wrote:
| > A programming language that's only good for < 100 line
| scripts is not a good choice.
|
| What a bunch of crap. It's so trivial to show very popular
| and useful programs written in Python that far exceed this
| number I'm not even going to do the work.
|
| What a lazy criticism.
| rendall wrote:
| From the community guidelines:
|
| > In Comments
|
| > Be kind. Don't be snarky. Converse curiously; don't
| cross-examine. Edit out swipes.
|
| > Comments should get more thoughtful and substantive, not
| less, as a topic gets more divisive.
|
| > When disagreeing, please reply to the argument instead of
| calling names. "That is idiotic; 1 + 1 is 2, not 3" can be
| shortened to "1 + 1 is 2, not 3."
|
| > Please don't fulminate. Please don't sneer, including at
| the rest of the community.
|
| > Please respond to the strongest plausible interpretation
| of what someone says, not a weaker one that's easier to
| criticize. Assume good faith.
|
| https://news.ycombinator.com/newsguidelines.html
| callc wrote:
| Hi rsyring, I made this comment out of experience.
|
| As python projects grow and grow, you need to do lots of
| support work for testing and even syntactic correctness.
| This is automatic in compiled languages where a class of
| issues is caught early as compile errors, not runtime
| errors.
|
| Personally I prefer to move more errors to compile time as
| much as possible. Dynamic languages are really powerful in
| what you can do at runtime, but that runtime flexibility
| trades off with compile time verification.
|
| Of course, every project can be written in any language,
| with enough effort. The existence of large and successful
| python projects says nothing about the developer
| experience, developer efficiency, or fragility of the code.
| rsyring wrote:
| All perfectly valid perspectives and I agree with most of
| what you wrote. But the comment above is pretty different
| from the tone/effort behind the comment I took issue
| with. :)
|
| In hindsight, I should have just left it alone and not
| replied which is what I usually do. But Python's
| popularity isn't an aberration. It's tradeoffs make sense
| for a lot of people and projects. The low effort bad
| faith swipes at it from subsections of the HN community
| got me a bit riled today and I felt I had to say
| something. My apologies for a less than constructive
| critique of your comment.
|
| Best.
| callc wrote:
| Thanks for your comment. I definitely could have worded
| mine better too with a bit more effort and context.
| maleldil wrote:
| > Don't tell me about using tools X, Y, Z, mypy, ...
|
| What's wrong with using tools that improve on common issues?
| I don't think I'd use Python without them, but ruff and
| pyright make Python a very productive and reliable language
| if you're willing to fully buy into the static analysis.
| stanleydrew wrote:
| > Is this just junior devs who never learned it
|
| Seems more like it's fallen out of favor with senior devs who
| have moved to Go/Rust.
| ajkjk wrote:
| you'd be crazy (senior or not) not to use Go for Go stuff and
| Python for Python stuff
| biztos wrote:
| I use both, with a preference for Go but I feel like I
| should be doing more Python just to keep it fresh.
|
| It seems like two of the main entries under "Python stuff"
| are "working with people who only know Python" and "AI/ML
| because of available packages."
|
| What are some others?
| ajkjk wrote:
| I mean... to oversimplify a bit, Python is for scripting
| and Go is for servers.
| pyuser583 wrote:
| I consider this self-inflicted. Pythons Async functionality
| is ... unfortunate.
|
| JavaScript has much more intuitive async syntax, which was
| actually borrowed from a Python framework.
|
| For whatever reasons, the Python folks decided not to build
| on what they had, and reinvents things from scratch.
| bee_rider wrote:
| I don't know anything about go. But Rust is more of a
| competitor to C and C++, right? It is sort of bizarre if
| these languages are butting heads with a scripting language
| like Python.
|
| Python compares fairly well to Bash or JavaScript or
| whatever, right? (Maybe JavaScript is better, I don't know
| anything about it).
| maleldil wrote:
| Rust has language features (often inspired by functional
| programming languages) that allow you to write pretty high
| level code.
| tombert wrote:
| I have had a somewhat unearned distaste for Python for the last
| decade or so.
|
| I mostly just don't like some of the design decisions it made.
| I don't like that lambdas can't span multiple lines, I don't
| like how slow loops are, I don't like some functions seem to
| mutate lists and others don't, and I am sure that there are
| other things I missed.
|
| But it really comes down to the fact that my career hasn't used
| it much. I occasionally have had to jump into it because of
| scripting stuff, and I even did teach it for a programming 101
| course at a university, but I haven't had a lot of exposure
| otherwise.
|
| For scripting stuff for myself, I usually end up using Clojure
| with GraalVM (yes I know about babashka), or nowadays even just
| a static linked compiled language like Rust.
|
| I don't really understand why people think that compiled
| languages can't be used for scripting (or at least task
| automation), honestly. Yes you have to add a compilation step.
| This involves maybe one extra step during development, but
| realistically not even that. With Rust I just do cargo run
| while developing, I don't see how that's harder than typing
| Python.
| Joker_vD wrote:
| msedit main.py && ./main.py !! !!
|
| But indeed, pressing F5 solves that for both Rust and Python
| dec0dedab0de wrote:
| why would you want a lambda to span multiple lines? How would
| that be any better than a function?
| tombert wrote:
| Because sometimes I want to have logic that spans multiple
| lines and I don't want to assign it a name. An easy example
| might be something with a `map` or a filter. For example,
| in JavaScript [1,2,3,4].filter(x => {
| let z = x * 2; let y = x * 3; let
| a = x / 2; return (z + x * a) % 27 == 2;
| });
|
| Obviously I know I could name this function and feed it in,
| but for one-off logic like this I feel a lambda is
| descriptive enough and I like that it can be done in-place.
|
| You're free to disagree, but I think there's a reason that
| most languages _do_ allow multi-line lambdas now, even
| Java.
| frutiger wrote:
| Off topic: you didn't use y.
| tombert wrote:
| You are right! Obviously this is just an ad hoc thing I
| wrote to show a point but I shouldn't be using
| superfluous variables.
| ddejohn wrote:
| > Obviously I know I could name this function and feed it
| in, but for one-off logic like this I feel a lambda is
| descriptive enough and I like that it can be done in-
| place.
|
| FWIW, you'd also have the benefit of being able to unit
| test your logic.
| tombert wrote:
| I mean, maybe, that's why your lambdas shouldn't be too
| long.
|
| I have done a lot of Haskell and F#, and I'm very
| familiar with the concept of "lifting", and yeah being
| able to individually test the components is nice, but
| even within Haskell it's not too uncommon to use a lambda
| if the logic doesn't really need to be reused or is only
| a couple lines.
|
| If you have a huge function, or you think there's any
| chance of the logic being reused, of course don't use a
| lambda, use a named function. I'm just saying that
| sometimes stuff that has 2-4 lines is still not worthy of
| having a name.
| dec0dedab0de wrote:
| Honestly, I don't really see the appeal of unnamed
| functions in general. I so rarely use lambdas that I
| wouldn't really miss them if they were gone. Just
| occasionally as a sort key, or in a comprehension.
|
| I have seen people do this in JavaScript quite often, but
| I always assumed there was some kind of underlying
| performance benefit that I didn't know about.
|
| As I think about it I guess it makes sense if you're
| passing a function to a function and you just want it to
| be concise. I could imagine using something like that off
| the top of my head, but then pulling it apart and giving
| it a name the moment I had to troubleshoot it. Which is
| how I currently use nested comprehensions, just blurt
| them out in the moment but refactor at the first sign of
| trouble.
|
| I think maybe I just have trouble seeing some of the
| braces and stuff, and it's easier for me to reason about
| if it's named. I guess that's why we have 32 flavors.
|
| Thanks for answering me honestly I really do appreciate
| it, even if my tone came off as dismissive. Sometimes I
| don't realize how I sound until after I read it back.
| tombert wrote:
| Obviously it's totally fine to have a difference of
| opinion for something like this.
|
| > I have seen people do this in JavaScript quite often,
| but I always assumed there was some kind of underlying
| performance benefit that I didn't know about.
|
| I don't think so, at least I haven't heard of it if there
| is.
|
| I tend to have a rule of thumb of "if it's more than 6-7
| lines, give it a name". That's not a strict rule, but
| it's something I try and force myself to do.
|
| Like in Python, _most_ lambdas can be done in one line,
| but that also kind of gets into a separate bit of gross
| logic, because you might try and cram as much into an
| expression as possible.
|
| Like, in my example, it _could_ be written like this:
| [1,2,3,4].filter(x =>((x * 2) + x * (x/2)) % 27 == 2);
|
| But now I have one giant-ass expression because I put it
| all into one line. Now where previously I had two extra
| names for the variables, I have the ad-hoc logic shoved
| in there because I wanted to squeeze it into a lambda.
| _dain_ wrote:
| Naming things is one of the hard problems of computer
| science. It's nice not to be forced into naming
| something.
| rs186 wrote:
| If your style is doing a lot of functional programming,
| multi-line lambda is a very natural thing to do. Other
| times you want to use a variable or several variables
| without actually passing it around as an argument. It makes
| sense especially if you are already used to it in
| Java/C++/JavaScript/Go.
|
| Is it "better" than a named function? No, of course, they
| work mostly the same. But we are not talking about better
| or not. We are talking about syntax just for the sake for
| syntax, because some people prefer to write code in a way
| you don't necessarily care about.
| dec0dedab0de wrote:
| This makes a lot of sense, I got to a similar conclusion
| in my other reply.
|
| I always thought the appeal of functional programming was
| more about test-ability and concurrency, it never
| occurred to me that people actually preferred the syntax.
| tombert wrote:
| Can't speak for anyone else, obviously, but part of the
| reason that I got into functional programming is
| specifically because I found the syntax very expressive.
| I felt like I was able to directly express my intent
| instead of describing a sequence of steps and hope that
| my intent comes to fruition.
|
| Different strokes and whatnot, not everyone likes
| functional programming and of course there are valid
| enough criticisms against it, but I've always appreciated
| how terse and simple it feels compared to imperative
| stuff.
|
| Even with regards to testability, if your function is
| pure and not mucking with IO or something, then even
| using a multi line lambda shouldn't affect that much. You
| would test function calling it.
|
| Keep in mind, Haskell doesn't really have "loops" like
| you'd get in Python; in Python you might not necessarily
| need the lambda because you might do your one-off logic
| inside a for loop or something. In Haskell you have map
| and filter and reduce and recursion, that's basically it.
| bko wrote:
| The most insane python feature is that for loops keep their
| intermediate variable.
|
| for x in [1,2,3]: print(x)
|
| x sticks around! So you'll always have these random variables
| floating around, and hope you don't use the wrong one.
|
| And to add insult to insult to injury, if you're using mypy
| for type checking you'll get a nice error if you try to reuse
| x with a different type:
|
| for x in ['a', 'b', 'c']: print(x) << Incompatible types in
| assignment (expression has type "str", variable has type
| "int") [assignment]
|
| And the types I can never trust. I've used all the tooling
| and you still get type errors in runtime. It's also
| ridiculously slow.
|
| I would also like optional chaining (e.g. foo?.bar?.baz) and
| a million other features that other high level programming
| languages have.
| nickdrozd wrote:
| > The most insane python feature is that for loops keep
| their intermediate variable.
|
| "Insane feature" is a generous way of describing this
| behavior. I would say it is just a stupid bug that has
| managed to persist. Probably it is impossible to fix now
| because of https://xkcd.com/1172/
|
| How typecheckers and linters should deal with this is a
| tricky question. There is how the language ought to work,
| and then there is how the language actually does in fact
| work, and unfortunately they are not the same.
| ActorNightly wrote:
| Comments like this basically should say "I want as much
| handholding as possible"
|
| Lucky for you, LLMs are pretty good at that these days.
|
| >And the types I can never trust. I've used all the tooling
| and you still get type errors in runtime. It's also
| ridiculously slow.
|
| IDE integrated mypy checking does this in the background as
| you type. As for errors, it all has to do with how much
| typing you actually use. You can set the IDE to throw
| warning based around any types or lack of type annotation.
|
| Again, handholding.
| m0llusk wrote:
| The v2 to v3 transition threw a lot of people.
| codethief wrote:
| Can we please stop reiterating the same old stories? That was
| years ago. Most Python devs these days never wrote a single
| line of Python 2. I learned it 16 years ago and, while
| frameworks like Django were still in the middle of the
| transition back then, I pretty much started learning &
| writing Python 3 right away.
| FredPret wrote:
| This might be true but I still find myself typing:
|
| print "xyz"
|
| now and then. It's not a big deal, but it reminds me of
| struggling with pip->pip3 and many other things for a long
| time years ago.
| ewoodrich wrote:
| Hah that brings back memories of me smugly insisting to my
| freshman roommate that using Python 3 tutorials to learn
| programming was a complete waste of his time and he should
| be using 2.7 for life like the rest of us l33t hax0rs.
|
| Tbf at that point Django was still pretty shaky with 3 and
| basically none of the 3rd party Django libraries supported
| it at all, plus I was using Google AppEngine which at the
| time was tightly coupled to the 2.7 runtime. But really I
| was just parroting the Slashdot hivemind which was 100%
| convinced the transition was the new Perl 6 and would kill
| Python, and that Python.org was dishonestly teaching
| newbies who didn't know better a dead language and
| worthless skill when they changed the default.
|
| Fortunately for him he ignored me and most of the big
| Django libraries were ported like a year later at which
| point I had to switch anyway to get updates. Fully agreed
| that in 2025 it's pretty much irrelevant, and honestly
| despite some legitimate pain the transition was much more
| successful than the cynics assumed it would be at the time.
| dec0dedab0de wrote:
| When it got big enough that companies were forcing people to
| learn it. People automatically hate things they didn't choose
| themselves.
|
| Plus there has been a rising sentiment against dynamic typing
| by masochists over the last decade or so.
| verandaguy wrote:
| > by masochists
|
| Hey! The masochism pays dividends. I can't do anything with
| duck typing that I can't also do with `dyn Trait` abuse :)
| dec0dedab0de wrote:
| HA! Alright Fair enough :-)
| macawfish wrote:
| After using Rust's tooling, Python's tooling is obscenely
| painful. Like intolerable. Which makes some of us feel
| overwhelmingly frustrated with the language itself. The amount
| of time I've squandered on Python because of its tooling... I'm
| never getting that back.
|
| But then uv came along. It's not just another poetry or pipenv
| or whatever. It works well and it has uvx and `uv tool install`
| and other nice things.
|
| Previously when I saw that something was written in Python I'd
| curse under my breath because I don't have the mental energy to
| make a virtual environment and source its shell script and
| remember where I put it just to try something out. On arch
| Linux I can't just pip install something without going through
| some crazy setup that I used to have patience for but as I get
| older it's been better to just curse that snake language
| altogether and spend time doing something more chill like
| writing rust.
|
| But now I can just type "uvx" and it works. I'm probably not
| going to start writing python again any time soon, but at least
| now I have less reason to be disappointed with people who
| themselves choose to write Python.
| jonas21 wrote:
| A decade ago, Python was pretty rough around the edges in
| production. Of course you could make it work, but you had to
| sacrifice a lot in terms of:
|
| - Environment / dependency management
|
| - Type safety
|
| - Performance
|
| As the author points out, these have largely been addressed now
| by uv, type hints, pydantic, FastAPI, etc.
| dccsillag wrote:
| Typing still sucks big time. Same for perf, unless you are
| working with numerics that fit with something like NumPy or
| JAX.
| ActorNightly wrote:
| >A decade ago, Python was pretty rough around the edges in
| production.
|
| Not really.
|
| Environment/dependency management is/was never an actual
| problem. People act like you update a version and stuff
| breaks. Even then, venv existed for this reason, and you
| could specify version in the setup.py or requirements.txt.
|
| Type safety should in theory be covered by unit tests. If you
| assign a variable to another one in a dynamic setting
| accidentally, like a string to a dict, then your
| functionality breaks. In reality though, its really not that
| hard to use different variable names. In my experience, the
| only time things start getting confusing is if you start
| using Java concepts with things like Factories and a lot of
| OOP and inheritance in Python. None of that stuff is really
| necessary, you can get by with dicts for like 90% of the data
| transfer. And in very type safe languages, you spend a lot of
| time designing the actual type system instead of just writing
| code that does stuff.
|
| Performance is still slow, but language performance doesn't
| really matter - you can launch natively compiled code easily
| from Python. Numpy was built around this concept and is also
| 10 years old. You will never beat C (with explicit processor
| instructions for things like vector math) or CUDA code, but
| most of your code doesn't require this level of performance.
| codazoda wrote:
| I haven't tried uv but my biggest pain point with Python has
| been the way env works. I always find it painful and odd.
|
| Backward compatibility, which I suppose is closely related to
| needing to use env, is also a pain. In my experience you can't
| go forward or backward in many cases. It's especially painful
| on projects that don't change very often. I'm sure that an
| active codebase can probably be kept updated from version to
| version, but if you've waited a bunch of versions, it seems
| painful.
|
| But, I'm not sure I've given it a fair shake because I haven't
| needed to. It's use in AI does make it an attractive option,
| now more than ever.
| taeric wrote:
| I think for a lot of us, it was very frustrating when it was
| being pushed with no real analog for the practices we had in
| other languages. Poetry used to be pushed as how to do
| dependency management, but it was not obvious that it was not
| necessarily your build manager, as well. Even today, I'm not
| entirely clear what the standard approach is for how to manage
| a project. :(
| macawfish wrote:
| If I were to try again I'd go with uv, it seems way way
| better
| taeric wrote:
| I have been sticking with poetry for a while, now. What
| would make me want/need to move to uv?
| cdelsolar wrote:
| yeah Poetry is fine
| macawfish wrote:
| Maybe you'll find this series of articles interesting:
| https://www.loopwerk.io/articles/tag/uv/
| taeric wrote:
| Thanks! I'm not entirely sure I see a reason to change on
| there, oddly.
|
| I'm very fortunate that my python projects are all
| relatively small, so maybe that colors things a bit.
| Certainly looks like something that would have swayed me
| to uv at the start, but as things are, I think I mainly
| just wish there was a more standard/accepted work flow
| for build and release.
| maleldil wrote:
| - Performance: uv is so much faster that some operations
| become transparent. poetry's dependency resolver is
| notoriously slow. uv being a native binary also means it
| has a faster startup time.
|
| - Interpreter version management: uv can handle separate
| python versions per project automatically. No need for
| pyenv/asdf/mise.
|
| - Bootstrapping: you only need the uv binary, and it can
| handle any python installation, so you don't need to
| install python to install a management program.
|
| - Environment management: uv will transparently create
| and update the environment. You don't need to source the
| venv either, you use `uv run...` instead of python
| directly.
|
| Overall, it makes common Python project management tasks
| simple and transparent. It also follows standards (like
| project definition metadata and lock files), which poetry
| often doesn't.
| taeric wrote:
| I'll pay attention to poetry soon. As is, I don't recall
| my builds ever going slow because of poetry. I don't
| think I've noticed it have any impact on speed, at all.
|
| I did just update the dependencies of some of my
| projects. I could see how that could be faster. I don't
| do that often enough for me to care about it, though.
| `poetry run pytest` is the slowest thing I have, and I'm
| confident most of that slowness is in my direct control
| already.
|
| I'm intrigued on the lock file point. I thought that was
| literally one of the main reasons to use something like
| poetry, in the first place? Does uv have a better lock
| file mechanism?
| whatever1 wrote:
| I think during the python 2-> 3 transition period (which was
| almost a decade long) a lot of people started looking into
| alternatives, because frankly that mess was the last straw. In
| the scientific domain this is when Julia started growing.
|
| Of course then crypto bros happened and the rest is history.
| _dain_ wrote:
| I think a combination of:
|
| - statically typed languages got better, reducing the relative
| benefits of dynamic typing. people realized they didn't really
| hate static types, they hated the way [insert 90s-00s
| enterprise language here] did static types
|
| - the GIL became more and more painful as computers got more
| cores
|
| - it used to be a language for passionate hackers, like a
| latter-day lisp (cf that old pg essay). "written in python"
| used to be a signal of quality and craftsmanship. now it's the
| most commonly taught beginner language; millions of bootcamp
| devs put it in their CV. average skill level plunged.
|
| - PSF was asleep at the wheel on the packaging / tooling
| problems for years. pip/venv are dinosaurs compared to cargo,
| nix, or even npm.
| photonthug wrote:
| Python is probably too awesome and versatile to go out of
| fashion, but as a long time user.. the ecosystem is
| frustrating. Dependencies and packaging have been, and still
| are a nightmare after _thousands of years._ Problems are
| fixable sure but the thing is that they never end. After you
| get plenty of practice fixing all the related problems, you 'll
| have to keep fixing them for yourself, your less savvy
| teammates, and in third-party code pretty much forever. This is
| worth it in exchange for "import antigravity" for the first 100
| years, but it's frustrating eventually.
|
| Everyone will mention uv/pyenv/poetry/conda/virtualenvs, so
| fine, let's pretend it's not a problem that you tried each of
| those in desperation and they are all household names. Suppose
| the packaging wars actually ended and everyone uses what you
| use without you needing to tell them, and suppose further that
| every pypa problem isn't blaming debian maintainers for obvious
| regressions. Pypi will still yank[0] packages _at the source_
| to perhaps randomly break deterministic behaviour, smashing
| anything in the blast radius rather than only clients using a
| --strict flag or something. You can pin your own dependencies
| but who knows what they will pin (nothing, or the wrong stuff,
| or the wrong way probably!) or what they will yank. Now for
| repeatability you need to host a mirror for everything you use-
| which is fine for corporate but a nonstarter for the novice and
| annoying for FOSS projects.
|
| If you have zero dependencies or a slowly changing environment
| that is receiving _constant_ care and feeding, you 'll probably
| never notice how bad things are. If you put down most projects
| for a month though and pick them back up, perhaps with a
| different environment, machine, or slightly different python
| version it's broken, bitrotted, and needs serious attention to
| be rehabilitated.
|
| People might argue.. that's just software dev. Nope. I say it
| with lots of love and gratitude for the efforts of the
| community.. but most langs/ecosystems would never tolerate this
| level of instability. One has to eventually just admit that
| working, portable, and actually repeatable environments with
| python basically just require docker. Can we talk about how "--
| break-system-packages" is hilarious? After you retreat to
| docker you can type this a few times a day, push the container
| up, pull it down months/years later, and then realize that
| literally the only way to get a stable working environment is
| to request a broken one. QED
|
| [0]: https://docs.pypi.org/project-management/yanking/
| whinvik wrote:
| Out of curiosity, why would I use Dataclass vs a Pydantic
| Basemodel. If we did not have a PyDantic dependency I could
| imagine wanting to use Dataclass. But if I have it, why not use
| everywhere?
| rsyring wrote:
| To help answer your question, here's a detailed comparison from
| the attrs project:
|
| https://www.attrs.org/en/stable/why.html
|
| There's some obvious potential for bias there, but I thought
| most of the arguments were well reasoned.
|
| Edit: found another that I thought was helpful:
| https://threeofwands.com/why-i-use-attrs-instead-of-pydantic...
| intalentive wrote:
| Performance hit from data validation at construction time. I
| like msgspec which is much leaner and faster.
| lysecret wrote:
| Main reason is (used to be) performance. But since pydantic 2.0
| it's not an issue anymore I default to use pydantic for
| everything.
| maleldil wrote:
| Unnecessary baggage if you don't need validation or
| serialisation.
|
| My rule of thumb is to use Pydantic if I need serialisation,
| otherwise I default to dataclasses.
| adammarples wrote:
| The Chad answer is to use pydantic.dataclass
| afiodorov wrote:
| My rule of the thumb is that Dataclasses are for compile-time
| type-checking, pydantic classes are for run time type checking.
| tauroid wrote:
| Why would I use a Pydantic model when
| `TypeAdapter(MyDataclass)` exists?
| simonw wrote:
| > I would like to have a tool that generates the project
| structure for me, but I haven't found one that fits me yet.
|
| I recommend cookiecutter for this. I have a few templates I've
| built with that which I use frequently:
|
| python-lib: https://github.com/simonw/python-lib
|
| click-app: https://github.com/simonw/click-app
|
| datasette-plugin: https://github.com/simonw/datasette-plugin
|
| llm-plugin: https://github.com/simonw/llm-plugin
|
| You can run them like this: uvx cookiecutter
| gh:simonw/python-lib
| timkpaine wrote:
| Copier is the new hotness for this
|
| https://copier.readthedocs.io/en/stable/
| oezi wrote:
| My take on this (using Ruby) is
| https://github.com/coezbek/baker
|
| It doesn't copy template repos, but rather creates a list of
| imperative steps to perform. Steps can be both manual (obtain
| an API key and store it here) and automatic (run 'uv init').
| Markdown syntax, ruby string interpolation and bash.
|
| It came from a deep hate for yml based configs.
| mmcnl wrote:
| Am I the only one who actually likes setting up new projects? I
| don't want to automate that.
| serial_dev wrote:
| It depends on your work, though...
|
| If you work at an agency or as a freelancer and you build
| various similar apps with similar tooling and base setup,
| being able to scaffold and have them all setup quickly, not
| having to do it manually and waste hours id important.
| Similarly, if you work on various small open source packages,
| you want the tooling to be the same, READMEs look the same,
| etc, a script or tool to "spit out" the basic structure can
| be nice.
|
| On the other hand, if you set up the app or larger open
| source package and you'll work only on that project for
| potentially years, setting up a project individually,
| organically makes a lot of sense.
| consumer451 wrote:
| This type of thing seems ripe for building into agentic LLM dev
| workflows, doesn't it?
| didip wrote:
| Honestly, these days, just tell AI to generate one for you.
| manofmanysmiles wrote:
| I make projects following almost identical patterns. It's a
| little uncanny. Maybe the people in the python developer
| ecosystem are converging on a pretty uniform way to do most
| things? I though some of my choices were maybe "my own", it
| seeing such consistency makes me question my own free will.
|
| It's like when people pick a "unique" name for their baby along
| with almost everyone else. What you thought was a unique name is
| the #2 most popular name.
| bobson381 wrote:
| as though subsurface pilot waves in every spectrum hold human
| egos as constituent particles - becoming-being lol
| solumos wrote:
| This sort of architecture has been in favor with python for at
| least 10 years or so, but I think you're right -- the structure
| just makes sense, so many reasonable engineers converge on
| using it.
| 0xbadcafebee wrote:
| Maybe I'm the only one that finds Python simultaneously verbose
| and lacking? Either you need 500 dependencies to do something in
| a simple way, or you need dozens (if not hundreds) of lines to do
| trivial things. I avoid writing Python because there's so much
| bullshit to add. Much prefer Perl, I can actually get things done
| quickly. Python feels like programming for the sake of
| programming.
| supportengineer wrote:
| dang the backend is leaking old comments from 2007
| mystifyingpoi wrote:
| Could you share an example, where Perl is quicker to use and
| more powerful?
| lucb1e wrote:
| And not write-only (https://handwiki.org/wiki/Write-
| only_language)
| wslh wrote:
| YMMV, but in my experience, Python's top use cases tend to
| require fewer dependencies, not more. Many trivial tasks are
| already built into the language. Not saying Python is perfect,
| but it's definitely well-oriented in that regard. I'm curious
| in what kinds of use cases have you found the opposite to be
| true?
|
| I think the classic Python vs. Perl question ultimately comes
| down to using what you feel most comfortable with. People are
| different, and that's totally fine.
| nickjj wrote:
| I have a bunch of zero dependency projects. You can get a lot
| done with the standard library and single file projects which
| you can run on most systems without needing to do anything
| except curl it down and run it since Python is available.
|
| For example here's a ~2k line Python project which is a command
| line finance income and expense tracker:
| https://github.com/nickjj/plutus/blob/main/src/plutus
|
| It uses about a dozen stdlib modules.
|
| About 25% of the code is using argparse to parse commands and
| flags. With that said, I tend to prefer code that yields more
| lines for the sake of clarity. For example this could
| technically be 1 or 2 lines but I like each parameter being on
| its own line. parser_edit.add_argument(
| "-s", "--sort", default=False,
| action="store_true", help="Sort your profile and
| show a diff if anything changed", )
| dndurbah wrote:
| > Much prefer Perl, I can actually get things done quickly
|
| Python lets you just nest data structures without having to
| twist your brain. You want a tuple in a list in a dictionary
| value: you just write it down and can access it with a unified
| notation. Bam. No reference madness and thinking about
| contexts. It's a big part of what I typically need to get
| things done quickly and understand how I did it 5 years later.
| That has to count for something. Python is boring in that
| sense, Perl is fun. But that's exactly my problem with it. It's
| too clever for it's own good and writing it does things to your
| brain (well at least mine).
| bobsmooth wrote:
| The best part about python is that there's a library for
| everything.
| milin wrote:
| Have you met Java?
| mekoka wrote:
| When you say "I actually can get things done quickly", does
| that include reading that same source a year from now?
| CraigJPerry wrote:
| I keep meaning to write something like this but exploring the
| "how simple can you make it" angle - a lot of my world is kube
| (which is great in the right scenario) but could you shave
| complexity out of a stack designed for solo dev rapid iteration:
|
| e.g. rather than: > It's important not to do any
| heavy data processing steps in the project-ui ... we keep the
| browser application light while delegating the heavy lifting and
| business logic to the server
|
| Chomp the complexity, serve HTML from the backend directly
| > ty
|
| Im curious where ty goes but for a min-complexity stack i couldnt
| spend complexity tokens on pre release tools >
| pydantic ... dataclasses
|
| One or the t'other, plus i'll forever confuse myself: is it
| post_init (dataclasses) or is it post_model_init (pydantic) - i
| had to check! > docker
|
| if we already have uv, could we get away without docker? uv sync
| can give an experience almost akin to static compiled binaries
| with the right setup. Its not going to handle volumes etc so if
| you're using docker features, this concept isnt going to fly. If
| you're not wedded to docker though, can you get away with just uv
| in dev and prod? in an enterprise prob not, i wouldn't expect to
| be able to download deps in prod. For flying solo though...
| > compose
|
| You've a frontend, a backend and presumably a database. Could you
| get away with just uv to manage your backend and a local sqlite
| db?
|
| So a broadly feature comparable stack for rapid iteration with
| less complexity but still all the bells and whistles so you dont
| need to cook everything yourself, might look like:
| - uv - fastapi + jinja + htmx + surreal + picocss -
| sqlite
|
| You could probably sketch a path to hyper scale if you ever
| needed it: - v1 = the above stack - v2 =
| swap sqlite for postgres, now you unlocked multiple writers and
| horizontal scaling, maybe py-pglite for test envs so you can
| defer test-containers adoption for one more scaling iteration.
| WAL streaming would add some complexity to this step but worth it
| - v3 = introduce containers, a container registry and test-
| containers. I dont think you really unlock much in this step for
| all that additional complexity though... - v4 = rke2 single
| node cluster, no load balancer needed yet - v5 = scale to
| triple node, we need a load balancer too - v6 = add agent
| nodes to the rke cluster - v7 = can you optimise costs,
| maybe rewrite unchanging parts in a more resource efficient stack
| ...
| jackbravo wrote:
| if you want to serve HTML from the backend, why not use
| FastHTML then ;-)
| CraigJPerry wrote:
| i experimented with it, i'm a fan of the concept. Ironically
| the bit i thought id like most (swap jinja extends
| shenanigans for just composing functions or callables more
| generally) is the bit that i didnt warm to. I dont really
| know why, on paper it ticks boxes for me. In practice i felt
| slow.
| mmcnl wrote:
| Ofcourse the most used programming language in the world is not a
| pain to use. How could it be #1 if it was?
| callc wrote:
| Funnily enough, I made the opposite switch recently, and am also
| liking it.
|
| My thoughts about python here:
| https://calvinlc.com/p/2025/06/10/thank-you-and-goodbye-pyth...
|
| Next time I get into Python I'll try uv, ruff, ty.
| frollogaston wrote:
| I switched from Python to JS for backend stuff a while back,
| thoroughly enjoying it. I agree that "Python installation and
| package management is broken," but the async stuff was the
| biggest improvement to productivity. Yes I know Python got
| asyncio, but there's a big difference between having one well-
| accepted way of doing things vs multiple competing,
| incompatible ways, where the good one has the least momentum.
|
| The rest is small stuff that adds up like Py whitespace
| scoping, or Py imports somehow not taking relative paths, or JS
| object syntax is nicer:
| https://news.ycombinator.com/item?id=44544029
| frollogaston wrote:
| I was like, switched from what, then eventually found a footnote
| "I used to be mostly a Java/JavaScript/R kind of guy"
| osigurdson wrote:
| >> I prefer to use a monorepo structure
|
| There is nothing more annoying than tons of little repos all of
| which containing tiny projects with a few hundred lines of code
| but (of course) you need most / all of them to do anything. Use a
| mono repo until there is some obvious reason to split it up imo.
| sethammons wrote:
| in my experience, repo by "area" works the best. This usually
| means by team, but you don't want a team restructure to cause
| code relocation issues. And, yes, only when the org pressures
| push for it.
|
| On the flip side, we have an org with 50+ teams and our
| operations team is pinning for a monorepo. They are just fine
| with one team's push forcing N teams to have an unexpected
| deploy and recycling of caches, connections, etc. Not to
| mention what will happen when team A doesn't have time to deal
| with team B's merge due to other org pressures.
| MonkeyClub wrote:
| I got the impression that TFA speaks of a monorepo in the sense
| of not splitting the backend and the frontend into two
| different repos.
|
| For personal projects, though, I get the value of an actual
| small projects monorepo.
| bognition wrote:
| I'm on board with most of this. The one suggestion I'd add is to
| replace "make" with "just"
| underdeserver wrote:
| I hear about it every now and again and I can't seem to grok
| the benefit. What's the killer feature over make?
| BeetleB wrote:
| If you're an expert in make and already have a Makefile, I
| would not recommend switching to just for that project.
|
| The benefit of just is that it's designed to be a command
| runner, whereas make is designed to be a build tool. justfile
| syntax is much simpler and more ergonomic. It also has nice
| features: Private recipes, submodules, recipes that you can
| specify to run only in a particular OS (we use the same
| justfile for both Windows and Linux), writing your recipes in
| a language other than your shell language, and many many
| other niceties.
|
| A new user can start doing "advanced" stuff in just in a
| couple of hours. They'll take a lot longer if trying to do it
| via make.
| kstrauser wrote:
| First, I grok make. I'm saying this from a position of
| familiarity, not of ignorance and fear.
|
| Make is great at compiling code in languages that don't have
| bespoke build systems. If you want to compile a bunch of C,
| awesome. For building a Rust or JavaScript project, no way.
| Those have better tooling of their own.
|
| So for the last 15 years or so, I've used make as a task
| runner (like "make test" shelling out to "cargo test", or
| "make build" calling "cargo build", etc.). As a task
| runner... it kinda sucks. Of course it's perfectly capable of
| running anything a shell script can run, but it was designed
| for compiling large software projects and has a lot of
| implicit structure around doing that.
|
| Just doesn't try to be a build system. It's optimized for
| running tasks. Here, that means it provides a whole lot of
| convenient functions for path manipulation and other common
| scripty things. It also adds dozens of quality-of-life
| features that devs might not even realize they wanted.
|
| For example, consider this trivial justfile:
| # Delete old docs clean: rm -rf public
| # This takes arguments hello name: @echo
| Hello, {{name}}
|
| If you're in a directory with it and run `just --list`, it'll
| show you the list of targets in that file: $
| just --list Available recipes: clean #
| Delete old docs hello name # This takes arguments
|
| That second recipe takes a required command line argument:
| $ just hello error: Recipe `hello` got 0 arguments but
| takes 1 usage: just hello name $
| just hello underdeserver Hello, underdeserver
|
| You can do these things in make! I've seen it! Just doesn't
| add things that were impossible before. But I guarantee you
| it's a lot harder to implement them in make than it is in
| just, where they're happy native features.
|
| There are a zillion little niceties like this. Just doesn't
| try to do everything make does. It just concentrates on the
| smaller subset of things you'd put in .PHONY targets, and
| makes them really, really ergonomic to use.
|
| You wouldn't use just to replace make in a large, complicated
| build. I would unhesitatingly recommend it for wrapping
| common targets in repos of newer languages, so that `just
| clean build test` does the same things whether you're in
| Python or TS or Rust or whatever, and you don't want to hack
| around all of make's quirks just to build a few simple entry
| points.
| pletnes wrote:
| Just is fantastic for any project - also non-code ones!
| tk90 wrote:
| Is there a Rust equivalent to this? I'd like to dive into a rust
| "api_starter" as someone with mostly NodeJS experience!
| noncoml wrote:
| Switched to python from what? R? Java? Javascript?
| yunwal wrote:
| For me, python is the closest thing to writing pseudocode that
| functions. Every time I have the instinct to gloss over a thing
| when writing it down (because it feels obvious in my head), it
| turns out that python has an intuitive abstraction for it.
|
| Coming from a mathy background I found it incredibly satisfying,
| although I've come around to other languages since.
| odyssey7 wrote:
| As a mathy person myself, I find the OOP leaning difficult to
| think about. Better equational reasoning, better lambdas, fewer
| side effects to worry about, avoiding mutation so that I can
| define something and still know what it is later during
| runtime, those are what help me think clearly. To me OOP is
| about the furthest paradigm from math that I've used.
___________________________________________________________________
(page generated 2025-07-16 23:00 UTC)