I get the argument if a programmer doesn't like dynamic languages in general, but not because one dynamic language has become too flexible.
Python even has limited generics now through mypy and pep 484.
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
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.
(As someone who has to deal with a lot of Unicode content, I consider Python 3 a blessing, but curious.)
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
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
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.
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 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.
i've moved some forward, its not that hard. still seems like a mess
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.
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...?
(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)
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.
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.
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.
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.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?
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.
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]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
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/nameStill neat though. Sometimes I wonder if I should learn REBOL (or Red?) or something.
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]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.
"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.
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!
Here you go, a sorted list of dict keys:
k = sorted(d.keys())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.
> 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.
Also because `sorted()` works on any iterable, whereas .sort only works on lists.
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."
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.
How do you even get them there? I mean, input() returns Unicode strings. So do all operations on text streams.
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.
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 unsemanticUnsemantic? 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.
Especially for numpy/matplotlib scientific stuff, I'd imagine Go would not be a suitable replacement (but maybe Julia would be).
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.