Hacker News new | past | comments | ask | show | jobs | submit login

This has ruined Python for me. Gone on far too long and Python3 ended up being technical churn anyway rather than technical innovation. Not worth the break. I ended up replacing Python.



While an unpopular opinion, I believe Python has lost its way too. "There should be one-- and preferably only one --obvious way to do it." - yeah I don't see it and that used to be one of the reasons I loved Python. They used to at least try for that to hold true, not it's like they try for the opposite. I much prefer Go these days.


I understand preferring Go for static typing or performance, but not because a dynamic language gives you more than one way to do things. If don't like that Python has gained too many features, why not use something like Lua? Why jump into a more restricted language that's going to require you to write more code?

I get the argument if a programmer doesn't like dynamic languages in general, but not because one dynamic language has become too flexible.


I looked at Lua briefly instead of Go, but it looks like the concurrency story is lacking. Go also has an enormous standard library which helps for quick tasks.


Go will probably be a mess in 20 years as well.


Yet still no generics.

Python even has limited generics now through mypy and pep 484.


> Yet still no generics.

You can use the gccgo runtime from Nim and get your goroutines and channels working with generics, macros and everything else Nim has to offer: https://github.com/stefantalpalaru/golib-nim


But where did you go?

I've been dragged kicking and screaming into Python 3, (which I still hate), but I don't see any higher ground to swim too.


TypeScript, and I'm absolutely loving it. So much of what I do is JS and this lets me do modern JS with many libraries and I get type safety. The only thing I can't accomplish with it, from local apps to webapps to mobile apps. I haven't used a better choice for goto language than TS. I completely understand your feeling though, I was in the same boat for a couple years till I tried TS.

I also like Go and all the Python replacements. Definitely cheering on the exodus from Python3. The alternatives are all good stuff. I don't believe in 'one true god', and that god is definitely no longer Python. Py3 is a bloated mess of feature soup with no performance enhancements, they got so much wrong with it and is a case study in how to mismanage a language migration.

I'd probably been onboard if they would've done a little better job. It seems the migration was for GvR and the rogue band of core devs (easier to maintain, their little pet project features) rather than the userbase that made Python what it is. They just did what was easiest for them and are pretty arrogant about it, saying they do the work so they decide. Ok, I'll use something else then with that attitude. The arguments for it are beyond silly and horribly uninformed, like "added support for unicode" is repeated ad nauseum.. I was using unicode with Python since 2.6. I can't tell if people really are that uninformed or lying to promote Python3. It was just already too big to do what they did and how they did it.

But I'm not going to debate that with anyone, happily using TypeScript now and never looking back. It runs faster on V8 than Python ever will and I'm able to do almost everything you could do in plain JS with it. Which is a significant array of tasks. Otherwise, while I reach for TS first all the time now, thinking about getting into Rust for its C ABI and performance for a reusable library idea that I have. TS/Rust is a potent combo and covers an astonishing amount of ground (and does it well). Both of them are very practical.


Curious, what do you hate about Python 3, or is it just hating the migration process?

(As someone who has to deal with a lot of Unicode content, I consider Python 3 a blessing, but curious.)


I have a whole blog post/rant brewing about that topic, but on the whole, I just think it feels like it was designed by committee rather than a visionary. They've abandoned the common usage case in favor of the corner case. It also makes it much harder to teach.

A few quick examples:

Base64 encoding returns bytes. Why would anybody _ever_ want that? The whole purpose of B64 encoding is to make something string-safe.

It's also now invalid to have this as a project structure: Name/name.py (with a Name class) in it.

Which I would say is literally the most sensible common project structure to have. Now you have to call the file with the name class 'core' or 'main' or anything besides the actual description of what it is. Of course, you'll get no help from the errors if you hit this problem.

"Dictionary view objects" are horribly unsemantic and annoying to teach. How is the language improved by having this no longer work `k = d.keys(); k.sort()`? Just give me a list.

I'm maintaining a fairly large and popular Python 2/3 project and all of the errors are coming from the Python 3 side, and the maintainability of the project has been decimated by needing to support both versions.

They should have just made a 2.8 with asyncio and unicode strings.

My hope is that somebody will make a new language that does to Python what Python did to C/Java. For day-to-day scripting, let's get really serious about programmer ergonomics, semantics and maintainability above all.


> Base64 encoding returns bytes. Why would anybody _ever_ want that? The whole purpose of B64 encoding is to make something string-safe.

No, it's to make something ascii-safe which is a completely different concern.

> It's also now invalid to have this as a project structure: Name/name.py (with a Name class) in it.

What?

    > mkdir Name
    > echo "class Name: pass" > Name/name.py
    > python3 -c "from Name.name import Name;print(Name)"
    <class 'Name.name.Name'>
> "Dictionary view objects" are horribly unsemantic

Unsemantic? They're just the opposite. keyviews and itemviews are now sets, which is semantically sensible and really useful to get the intersection of two dictionary keysets, the only missing part is being able to subdict based on a keyset.

> Just give me a list.

    list(d.keys())
Why are you even using .sort()

> unicode strings.

That's what broke compatibility FFS, that's the entire reason why the maintainers felt they could change the rest of the language.


There are other scripting languages that have good support and strong communities. There doesn't need to be yet another programming language. Use Ruby, JS or PHP 7 instead. If it's scientific computing, Julia fills the niche very nicely. Or R.


My point is that we should go a level "higher" than any current offering.

Ex, why not let me do something like this out of the box:

    get https://api.github.com/users/Miserlou as miserlou
    print "My name is " miserlou.name
Transparent/automatic web requests, content-type checking, serialization parsing, string formatting, network reference parsing, etc. Let the user be more specific if they need to, but design heavily around the most common use case.


This is the kind of stuff Rebol wanted to do, although i don't know if it covered this particular case.


Yep, the moment I saw that I though "REBOL"! (Actually, I thought of Red, but same idea.)

Still, it seems that this is not thought through properly. What should the language do if the server does not return JSON? And can't we basically do this in Python already?


It's a trivial example, but the point would be that the stdlib would have the ability to

a) Speak flutent HTTP b) Understand Content-Type c) Deserialize to a common format

all completely transparently. If the server returned XML or MsgPack, it wouldn't matter, the code would work the same.

Ideally, we could imagine this going a step further, and having the language speak REST entirely.

Python's requests is a nice prototype, ergonomically speaking, but we can go much further.


There is nothing currently built into Rebol stdlib that replicates exactly this. But here's an example of how it could be done...

    import <json>
    import <xml>

    load-*: function [site] [
        p: open site
        content: read p
        http: query p
        close p

        parse http/headers/Content-Type [
              "application/json" return (load-json content)
            | "application/xml"  return (load-xml content)
        ] else [
            fail "Content-Type not recognised"
        ]
    ]

    miserlou: load-* https://api.github.com/users/Miserlou
    print ["My name is" miserlou/name]


Is this hypothetical, or does the stdlib actually have load-json and load-xml?


Above works, the <json> & <xml> imports are pulled off this remotely hosted common library - https://github.com/r3n/renclib

You'll need the Ren/C branch of Rebol 3 for this:

* repo - https://github.com/metaeducation/ren-c

* pre-built binaries - http://metaeducation.s3.amazonaws.com/index.html


Okay, as someone who doesn't know REBOL, what is the effect of miserlou/name if the server returns XML? The string value of a top-level <name> tag?


Ah this was a different XML module than I was thinking of because this is complete DOM parser!! But even so it does produce (by default) a flat representation of the XML.

So, if for example, Github did return XML and it looked something like this (shown in Rebol console):

    >> x: load-xml {<root><name>Mr Miserlou</name><login>xxx</login></root>}
    == [
        <root> [
            <name> "Mr Miserlou"
            <login> "xxx"
        ]
    ]
So to get top-level tags it's just:

    >> second x                                                              
    == [
        <name> "Mr Miserlou"
        <login> "xxx"
    ]
Now load-json also has a flat option so that a good way to unify things. Here's an updated example showing this:

    import <json>
    import <xml>

    load-*: function [site] [
        p: open site
        content: read p
        http: query p
        close p

        data: parse http/headers/Content-Type [
              "application/json" return (load-json/flat content)
            | "application/xml"  return (second load-xml content)
        ] else [
            fail "Content-Type not recognised"
        ]

        ;; next 2 lines just turns it into a hashmap so can do:  miserlou/name
        ;; without it could have done:  miserlou/<name>
        ;;
        for-skip data 2 [data/1: to-word to-string data/1]
        make map! lock data
    ]

    miserlou: load-* https://api.github.com/users/Miserlou
    print miserlou/name


Okay, that's quite good! I'm going to see how good this can get with the Python std lib later. Probably not quite this nice.


Actually, I think I was wrong. You can get something this nice in Python. It just requires a bit more glue code in the case of JSON, and a lot more glue code in the case of XML. All told, I figure Python might 10x more code than REBOL here. I'm not sure if it's fair to hold this against Python though. It's "just" a question of libraries. And it's only fair to hold libraries against a language if the library itself would be hard to write. Which in this case I think it wouldn't.

Still neat though. Sometimes I wonder if I should learn REBOL (or Red?) or something.


Um, what if the server returned, say, a JPEG? Or a plain old HTML webpage, complete with inline CSS and script tags?


Very close!

Here's an example using latest build of Rebol 3 (Ren/C branch)...

    import <json>
    miserlou: load-json read https://api.github.com/users/Miserlou
    print ["My name is" miserlou/name]


I like that! Are you sure there isn't some language that does this already?


> `k = d.keys(); k.sort()`? Just give me a list

Here you go, a sorted list of dict keys:

    k = sorted(d.keys())


You've completely missed the point. I'm not saying it can't be done, I'm saying that the new way is stupid.

In Python 3, I have to tell my students that

   breakfast = ["bacon", "eggs"]
   sorted_breakfast = breakfast.sort()
works, but

   breakfast = {"bacon": 2, "eggs": 3}
   sorted_breakfast = breakfast.keys().sort()
doesn't. They will ask, "why?", and I have to say "just because."

Instead, you have to use "sorted", even though "sorted" isn't even a verb, it is a property. "Why is sorted() rather than sort()" - "just because."

Similarly, "where is there a b'' in front of my name", why can't it find my module, and on and on and on.

The advantages of Python of a teaching languages are mostly gone now, and I would probably use JavaScript to teach beginners now, whereas I previously would have used Python2.7.


> In Python 3, I have to tell my students that

> breakfast = ["bacon", "eggs"]

> sorted_breakfast = breakfast.sort()

> works

Well, some of your students might point out to you that your `sorted_breakfast` is `None`, because that is what `sort()` returns, and even this example doesn't work as you have wanted ;)

On the other hand, if you have used `sorted(breakfast)` (and `sorted(breakfast.keys())` in other example), both examples would work as intended, and you couldn't blame Python 3.

> "Why is sorted() rather than sort()" - "just because."

It is not "just because", it is because it returns a sorted list (which is exactly what you wanted), compared to returning None.


> It is not "just because", it is because it returns a sorted list (which is exactly what you wanted), compared to returning None.

Also because `sorted()` works on any iterable, whereas .sort only works on lists.


I know that the best way to learn is "see one, do one, teach one" but I wish you'd put more effort into learning the language before teaching it.

The python.org tutorial and FAQ have answers to these questions.

I think it's unethical to tell a student, "just because" instead of, "I don't know why."


You're replying to the wrong person. I'm not the one who is doing teaching, I'm just the guy who corrects the teacher who hates Python 3 (for wrong reasons) ;)


Sorry about that.


FYI... neither of those work. Sort (using the dot sort() notation) operates on a mutable list in place, and returns no value. Never use it on the right side of an assignment. Its like dict's `update` in that regard.


your example sorted_breakfast doesn't work, in python 3.5 sorted_breakfast == None. Sort is a verb that modifies the receiving object, sorted is for returning a new object that is a sorted copy of the original, so you need to allocate two times the object.

Returning an iterator instead of a list has the advantage of not having to create a new object in case that is not needed, for example if you are going to filter a big dictionary just to obtain a few items then copying the keys of the dictionary and then filtering is not a good way of using memory efficiently.


> Similarly, "where is there a b'' in front of my name"

How do you even get them there? I mean, input() returns Unicode strings. So do all operations on text streams.


In [1]: breakfast = {"bacon": 2, "eggs": 3}

In [2]: sorted(breakfast)

Out[2]: ['bacon', 'eggs']

Done. One and only one obvious way to return a sorted list of keys of a dict.


>Base64 encoding returns bytes. Why would anybody _ever_ want that?

What corner case do you think python 3 is solving with the return type being a byte array? Surely you must have looked into it because clearly it isn't arbitrary ... Right?

>The whole purpose of B64 encoding is to make something string-safe

Guess again.


From Wikipedia:

"Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation."

Binary. To. Text. As in - bytes in, text out. Come on now.


Its intentional, in part because of all the mayhem caused by Python2's "free-spirited" view on whether a thing is bytes or text. And that "free-spirited" view caused A LOT of mayhem.

Python3 errs on the side of not converting bytes to strings or vice versa unless its an explicit conversion on the bytes/string object itself. And it is fan-fucking-tastic!


How do you feel about this:

https://github.com/naftaliharris/tauthon


i dont do a lot of python, and i think 3 is an improvement

but for me the real nightmare is all of the libraries. some have 2 and 3 support, some only 2, some with a 3 fork thats not maintained, etc etc.

every time i try to start a project using 3 i end up wasting a lot of time and going back to 2 anyways


Personally, I haven't found any must-have libraries for Python 2 only that don't have a satisfactory Python 3 alternative.


This is my major confusion as well. It seems not worth it to begin work in an older version because debt is inherent right at the start, and updating code (for a new language version) is a personal peeve (or irritant). It's irrational, so don't ask, but I avoid it everywhere I can.

Of course, diving into the newer version also adds a lot of debt, and possibly a total impasse, due to the lack of libraries that have made the update.

I guess it will be quite some time before it becomes foolish to still cling to py2


What libraries are unavailable in Python 3?

This gets mentioned in every hacknews thread on this subject, but I honestly don't believe I've seen any that weren't either already updated to support Python 3, or didn't have alternatives that worked just as well.

https://python3wos.appspot.com/ has a list of the largest packages in pypi, and there's very few that aren't available in Python3. httplib2 is easily replaced by requests. Supervisor isn't a library, it's an application. Same with carbon and graphite-web. Basically the only things on that list are the mozilla libraries, but IIRC some of those are in progress of being ported anyway.

Twisted is one of the few I can think of that still isn't there, but most of the core APIs are there, as well as a lot of secondary stuff - half a year ago, more than 90% of the unit tests were passing on python3.


I can't offer you any kind of solid case. My Python experience is admittedly limited. I've been working to get more into it lately.

Thanks for the resource.

Can I ask if you see any reason to not abandon Python 2 altogether when starting a new development project?


If you control the deployment environment, none that I can think of.

If not, and you need to deploy to RHEL/Cent 7, then maybe. They're still on 2.7, though software collections will let you install 3.x on either of them.


Oh thanks for the tip. I work with CentOS regularly, but haven't worked on a Python project in that environment yet.


idk, two sound libraries, an image processing library.

i've moved some forward, its not that hard. still seems like a mess


I, being a sysadmin, still consider Python 3 this new, shiny thing that is yet to become widely used. Linux distributions still use Python 2 code for their infrastructure, so Python 3 is something big I would need to specifically order to install that would give me negligible gains.


The Red Hat family of distros being decades behind isn't really an indication that things they aren't using are new and shiny. Plenty of modern distros ship Python 3 as the default Python, including Ubuntu. RHEL6 still uses Python2.6! It's horrid.

I'm also a sysadmin, and not a programmer. But I do a lot of my automation scripting in python, and have worked on a few larger projects in python, including one that's requirements meant it had to be Python2/3 compatible. I am not a fan of Python prior to 2.7 at all, and I think 2.7 is really just a bunch of bandaids trying to pull together a pretty crappy language, whereas 3.x is a joy to work with.


> The Red Hat family of distros being decades behind isn't really an indication that things they aren't using are new and shiny.

I talk about how a sysadmin perceives the state of Python, and a sysadmin usually works with stable OSes. And you know what? Most of the major distributions commonly used for servers use Python 2 as the default interpreter. The list of these distributions includes Red Hat/CentOS 7, Debian stable (Jessie) and soon-to-be-stable (Stretch), and Ubuntu 16.04 LTS.

> Plenty of modern distros ship Python 3 as the default Python, including Ubuntu. RHEL6 still uses Python2.6! It's horrid.

Erm... You compare "modern distros" with a release that is on its LTS? You know you're being unreasonable, right? Not to mention that Python 2.7 was released in 2010, the very same year as RHEL 6. It's hard to hold it against Red Hat having this in mind.

And how Ubuntu ships Python 3 as the default version? From what I see, in Ubuntu Zesty (17.04, i.e. the most recent release) package "python" has version 2.7.13-2.

> I am not a fan of Python prior to 2.7 at all,

Because...?

> [...] I think 2.7 is really just a bunch of bandaids trying to pull together a pretty crappy language,

Like...?

> [...] whereas 3.x is a joy to work with.

Becuase, in contrast to 2.x, it has the feature of...?


You do need to be careful when arguing about names: the official upstream advice from the Python core team is that, for example, invoking "python" (just "python") should always execute Python 2 (or report "command not found" if no Python 2 is available). Invoking Python 3 should always be "python3".

(the reason for this is to avoid breaking ancient scripts which naively assumed that "python" would always refer to Python 2, and allowing Python-3-aware scripts to be explicit about what version they were targeting)


Debian has included Python 3 since Squeeze.

The Ubuntu 16.04 Canonical provided AMIs on AWS don't even include Python 2, though it appears to be back in 16.10 and 17.04 from my double checking - but on 16.04, there is literally no python27 without installing it via apt.

RHEL and Cent have had Python 3 available in software collections since 6

And yes, since 6 is still not EOL the fact that they are still on 2.6 by default is something I can hold against them.

But per PEP standards, python should always be python2.x, and if it's not installed, not work at all. python3 should always be python3.

As for why I didn't like 2.6: 'io' performance was quite low, and much of what I've worked on makes heavy use of it. The C rewrite solves this. Lack of support in logging for logging over TCP. Being restricted to a single context manager when using with. Optparse instead of argparse. The lack of dictionary comprehensions (and I guess set comprehensions too, but I don't really use sets too frequently).

Why is Python 2.7 still not at Python 3 levels? I do a lot of work with international characters. That right there is enough, really. Outside of that? Just so much stupidity. Parts of the standard library with inconsistent names. Why are some libraries capitalized? Queue vs queue. Lack of asyncio.


> The Ubuntu 16.04 Canonical provided AMIs on AWS don't even include Python 2, [...] there is literally no python27 without installing it via apt.

Guess what? Freshly debootstrapped Debian doesn't have Python installed at all, too. And guess why? Because all the essential tooling in Debian is compiled. But then there is optional tooling, and Python 3 is yet to be used there.

But we were not talking about what interpreters are in a default installation. We were talking about Python 3 being the default Python.

> And yes, since 6 is still not EOL the fact that they are still on 2.6 by default is something I can hold against them.

No, you cannot. The primary thing RHEL provides is stability.

> Lack of support in logging for logging over TCP.

(1) Not like you cannot add it trivially. (2) It's not a good idea to work in Python's logging with unreliable things like network. You should always isolate Python logging from those things by using spooler. BTDTGTS.

> The lack of dictionary comprehensions (and I guess set comprehensions too, but I don't really use sets too frequently).

Of course, because those are essential part that cannot be trivially emulated by dict() constructor.

From all you said, only I/O performance, context managers, and lack of argparse are somewhat sensible arguments. They sum up to too little for me to consider them a significant difference in how it feels to write code (not to mention that optparse is adequate and I don't see argparse as much of a progress), but then I normally use half a dozen of other languages and runtimes, so I have a different perspective.


Python is Ubuntu's preferred language for system tools, and these now run under Python 3. Both Debian and Ubuntu have policies of using Python 3 wherever possible. The "python" command still invokes Python 2 to make sysadmins' lives easier.[1]

[1] https://www.python.org/dev/peps/pep-0394/


>> [...] whereas 3.x is a joy to work with. >Becuase, in contrast to 2.x, it has the feature of...? Unicode strings makes my life a lot easier when dealing with anything international. Pretty much every difference made was better for the language.


Nobody expects sysadmins to use shiny new things. When you guys use something new, its because its actually already probably old - at the very least, its no longer shiny, and possibly even moldy. And even then you grumble about it. =)


+1.. exactly my experience with sysadmins.. install all of the just developed software of the devs on a 4+ yeah old rhel 6.5 (with custom packages for everything of course) so it's stable and tested and we can haz red hat support which we never use.


I've very happily replaced Python with Go (backend online services, misc command line tools).


And that's a good fit for Go, but Python is used for lots of other things.


Oh for sure, which is why I specified.

Especially for numpy/matplotlib scientific stuff, I'd imagine Go would not be a suitable replacement (but maybe Julia would be).




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: