
Things to use in Python 3 - ausjke
https://datawhatnow.com/things-you-are-probably-not-using-in-python-3-but-should/
======
DonaldPShimoda
> __Type hinting (3.5+) __

> Static vs dynamic typing is a spicy topic in software engineering and almost
> everyone has an opinion on it. I will let the reader decide when they should
> write types, but I think you should at least know that Python 3 supports
> type hints.

I think this gives readers the impression that type hints have anything to do
with dynamic vs. static type systems, which isn't true. These are merely
annotations that are attached to values. In fact, it's legal to use full
strings as type annotations — they have no inherent semantic value.

You can _gain_ semantic value by using a tool like MyPy or an IDE like
PyCharm, but the type annotations do not in themselves _do_ anything. I think
it could be worth clarifying this for readers who are unaware.

~~~
BerislavLopac
The most underrated part of type annotations are so-called stub files [0],
which allow you to keep your annotations separate from the actual code, thus
reducing its size while still benefiting from the static analysis with mypy.

Unfortunately the IDE support for those files (.pyi extension) is quite
limited -- I have even suggested to the PyCharm team to implement an option to
automatically save all annotations to stub files, while still displaying them
alongside the code in the editor.

[0] [https://www.python.org/dev/peps/pep-0484/#stub-
files](https://www.python.org/dev/peps/pep-0484/#stub-files)

~~~
NelsonMinar
I'm sort of sad that Python has reinvented .h files.

~~~
ASalazarMX
Same here. Fortunately those files are entirely optional and apparently
seldomly used, judging by the limited IDE support after 5 years.

------
k4ch0w
F strings have been amazing in my everyday programming. I have been
programming in Python for about 8 years now. I'd say some additions to this
list are

    
    
      Conda for managing environments and Deep Learning builds such as Cuda on Ubuntu
     
      Jupyter notebooks for quick prototyping
    
      IPython if you have never seen it before.
    
      Requests Library

~~~
ehsankia
They just added a brand new feature in 3.8 that let's you just append = at the
end for quick debugging:

>>> f'{5+5=}'

'5+5=10'

>>> foo = 5

>>> f'{foo=}'

'foo=5'

[https://docs.python.org/dev/whatsnew/3.8.html#f-strings-
now-...](https://docs.python.org/dev/whatsnew/3.8.html#f-strings-now-support-
for-quick-and-easy-debugging)

~~~
gizmo385
This just feels like another example of Python slowly creeping more esoteric
syntax into the language, making it harder for beginners to approach the
language.

~~~
jplayer01
Beginners don't have to know or touch any of this though. They can keep using
normal strings until at some point they learn about f strings and see a need
for them. You don't need to stop adding features to a language just because a
beginner won't be able to learn everything. They don't need to.

~~~
simonh
I think the point is, a beginner coming across some code using such esoteric
features is going to be a bit lost as to what's going on. With most of Python
you can see what it's doing even if you didn't know the syntax before. That's
true of basic f-strings, but not so much with some of this stuff.

~~~
makapuf
Yeah languages are meant to be read even by beginners. I think a language like
python shines by being small (in design) yet powerful (by capability). Having
myriads of "nice for one use case" feature in the language is not the way
forward. I long for the time where % format and .format are removed from the
language spec. Even if they still work on the implementation for
compatibility. Please remove things.

~~~
batisteo
> Please remove things.

We're not done with Python 2 yet. This would be a Python 4 for sure. That's
not according the philosophy of backward compatibility of Python (even if I
agree with you).

~~~
makapuf
Yes backward compatibility is not an option (lets avoid redoing python3 trauma
) and simply delegating coexistence of old and new features to implementation
is a bit lazy. However documenting one way as the current one and other
features as old ways, for backward compatibility can simplify things.

------
alexgmcm
I just want to thank the author for not using Medium.

Far too many tech blog posts use that platform now and I don't like it very at
all as it feels really bloated and I can never be sure if what I'm about to
click is a 'premium' Medium post or not.

~~~
skocznymroczny
I like that the article doesn't have generic meme images separating each
paragraph.

~~~
yzssi
A few years ago complaining about that would get you flagged. Now it gets
upvoted.

~~~
chrshawkes
I talked about not using it years ago on my YouTube channel and got a rash of
shit. I've shown how to replicate that site in minutes as well.

------
auscompgeek
In case anyone is stuck on older versions of Python for any reason, here are
some backports of some of the listed features:

* f-strings: [https://github.com/asottile/future-fstrings](https://github.com/asottile/future-fstrings) (this is a pretty crazy hack, all the way to Python 2)

* pathlib: [https://pypi.org/project/pathlib2/](https://pypi.org/project/pathlib2/)

* typing: [https://pypi.org/project/typing/](https://pypi.org/project/typing/)

* enum: [https://pypi.org/project/enum34/](https://pypi.org/project/enum34/) (doesn't include any additions in 3.5+)

* functools.lru_cache: [https://github.com/jaraco/backports.functools_lru_cache](https://github.com/jaraco/backports.functools_lru_cache)

* dataclasses: [https://github.com/ericvsmith/dataclasses](https://github.com/ericvsmith/dataclasses) (3.6 only, requires ordered class __annotations__)

I'm half-expecting someone to come along with a hacked-up Python 2 backport
for implicit namespace packages :)

~~~
isaacremuant
With that in mind, the end for Python 2 is less than 8 months away.

Something fun to help people feel the "impending doom" and port their
projects:

[https://pythonclock.org/](https://pythonclock.org/)

~~~
kragen
Python 2 is free software. Nobody and no proper subset of people can
unilaterally end it. It ends when people stop using it, writing patches for
it, and sharing those patches. There might be a lacuna of coordination when
the current maintainers step down in 8 months, but the leftover stubborn
Python 2 users will come up with some way to share their patches for,
probably, decades.

------
rcfox
SimpleNamespace[0] is pretty handy too. It essentially lets you wrap a
dictionary and access its keys as member properties.

Also, it's kind of weird that the article would mention type annotations and
then not mention mypy[1].

[0]
[https://docs.python.org/3/library/types.html?highlight=types...](https://docs.python.org/3/library/types.html?highlight=types#types.SimpleNamespace)

[1] [http://mypy-lang.org/](http://mypy-lang.org/)

~~~
rattray
Curious to see a small code sample illustrating typical usage of
SimpleNamespace if you care to share? Docs didn't include one.

~~~
rcfox
Here's one case I've used it for:

    
    
        foo = json.dumps({'a': 1, 'b': {'c': 2}}) # Pretend you've downloaded some JSON...
        bar = json.loads(foo, object_hook=lambda x: types.SimpleNamespace(**x))
        print(bar.a)
        print(bar.b.c)
        print(bar.b.d) # Error
        bar.b.d = 3
        print(bar.b.d) # Works now
    

I mean, you could pretty much do the same sort of thing with namedtuple,
except this is mutable and doesn't require a pre-declaration of the keys. It's
easier to write off the cuff.

~~~
rattray
Cool, thanks!

------
fulafel
Originally small dynamic languages like Python and Javascript are constantly
growing new language/stdlib features but rarely taking anything away. I wonder
how this affects learnability, how long will it take for a programming newbie
to be able to jump into an existing project or read other people's code. I
guess this could be measured and studied, I wonder if someone has done it.

I think Python was probably at a pretty good local sweet spot in the
complexity:power ratio around the 2.0 version.

~~~
yen223
Python is definitely heading down that dark path.

I wonder how many pythonistas are fully across all of the new syntax coming,
like positional-only args or even the infamous assignment expression.

~~~
voldacar
Yes! Python is getting less pythonic with each new version.

~~~
baq
i prefer to see it the glass half-full way: the definition of pythonic
continuosly evolves.

------
sametmax
I'm training people in Python regularly and my classroom experience is: ALWAYS
USE __INIT__.PY EVERYWHERE. Don't use this namespace feature. You think you
understand how it works, but you don't. It will bite you.

~~~
scrollaway
Amen. Much as I wish python importing was as powerful as js, that ship has
sailed and we're nowhere close to getting rid of the dunder-init file.

Also pathlib is .. urgh. This is one of those that shouldn't be in the stdlib.
I don't get why it is, but requests isn't.

~~~
masklinn
> Much as I wish python importing was as powerful as js

In what way is python importing less powerful than JS? My experience is very
much the opposite (to the extent that JS even has an import _system_ ).

> I don't get why it is, but requests isn't.

Because pathlib was proposed (PEP 428), considered useful and self-contained.

The requests project does not want it to be included (this was discussed at
length back in 2015), and it would require merging chardet and urllib3 into
the stdlib first.

~~~
scrollaway
My post was unclear, it's fair that base JS doesn't have an import system; I
was talking about ES6 imports.

And yes I'm aware _why_ requests isn't in the stdlib, but that doesn't make it
"correct". And chardet should definitely be in the stdlib. I mean, ffs,
`mimetypes` is in the stdlib. urllib3 is more contentious but honestly? It
probably should be as well.

------
IanCal
Beware lru_cache and mutable objects. I'm on a phone so this will probably
contain an error but:

    
    
        @lru_cache
        def slow():
            return {"result": "immutable?}
    
        answer = slow()
        answer["result"] = "no"
        print(slow())

~~~
IanCal
Can't edit now, but here's a runnable gist
[https://gist.github.com/IanCal/d703106344e876728d2aaef67800d...](https://gist.github.com/IanCal/d703106344e876728d2aaef67800dfb8)

------
j88439h84
The "Implicit namespace packages" item is not correct. Those are for a a
specific packaging scenario which doesn't come up in normal usage. Packages
should have an __init__.py file in general.

~~~
giancarlostoro
If the file is going to be empty I fail to justify the effort. It is
implicitly a package. Is there a case where an empty init file makes sense in
Python 3?

~~~
nerdponx
Its absence distinguishes a non-package from a package.

------
gbajson
The example of f-string in the article is quite unfortunate, it suggests using
it for logging messages. F-strings shouldn't be used in loggers, because they
aren't lazy evaluated.

~~~
masklinn
TBF for the vast majority of logging it doesn't really matter. Not to mention
the laziness is only the (usually cheap) formatting itself. If you're logging
the result of non-trivial expressions (which would otherwise not be computed
at all) you have to handroll it.

f-strings are mostly unusable for translatable contexts. And format-strings
also don't work then (they're a security issue).

~~~
gbajson
I already experienced performance issue, just because log messages
(millions/s) were evaluated, for logger in debug mode, so it really depends on
the system.

------
jedberg
Wow, today I learned about f strings. That will make my code so much more
readable! And no more annoying bugs because I skipped one of the seven
references in the string!

~~~
mixmastamyk
It reads like sarcasm, but then you drop a real benefit. _((Confusion by New
Order playing in the background))_

~~~
jedberg
No it’s true enthusiasm. The internet has just ruined ! For everyone. :)

~~~
mixmastamyk
Glad to hear you like it. As a fun fact (and self-back patting), it was I who
braved the gauntlet at the python-ideas mailing list to get the idea accepted.
Eric Smith did everything else so deserves the credit.

Background: turns out that the string prefix was the only ASCII syntax left in
Python3, that's why it was chosen. The name "eff string" makes me cringe, but
once it stuck there was no stopping it.

~~~
DonaldPShimoda
> it was I who braved the gauntlet at the python-ideas mailing list to get the
> idea accepted

That explains why you're all over this post ;)

Fantastic feature, though. Really. Thanks!

Out of curiosity, what name would you have preferred over "f-strings"? "Format
strings"? "Interpolation strings"? "I-will-evaluate-expressions-in-curly-
braces strings"?

~~~
mixmastamyk
Well, I usually participate in Python threads. This post had only one part on
f-strings.

What to call it? Anything I guess. String interpolation is what it is called
elsewhere. But the f prefix is what everyone sees, though as mentioned, it is
only an implementation detail because other forms of syntax were already
spoken for. I personally chose f for "format."

Early on Guido changed the scope to include expressions as well. People were
already starting to say "eff string" so I changed my proposal to "e-string"
for "expression." I also like the sound of it better, sounds like email, etc.
But Guido (and Eric) decided to stick with f. Maybe because Guido learned
English later he doesn't realize how unfortunate it sounds. But, years later
we use the "iPad" and forget it sounds like a feminine napkin. So, no big deal
in the end.

------
whalesalad
Don't forget @singledispatch! Every once and a while this tool is glorious for
a polymorphic handler. Ie, `process_entity` that will fan-out to
`process_movie` or `process_tv_show` etc...

I miss it in a Python 2.7 project I am on right now.

Link to the docs:
[https://docs.python.org/3/library/functools.html#functools.s...](https://docs.python.org/3/library/functools.html#functools.singledispatch)

It's the same concept as clojure's defmethod.

------
nerdwaller
Another useful feature of 3.7+ (also available as a backport by the same name)
I’ve not seen mentioned is: ContextVars

The gist is you get a single interface for any type of threadlocal storage
that also works with coroutines (asyncio). I use it pretty consistently for
context logging of long running processes in our systems. However it has
implications on other concurrency paradigms usages as well.

[https://docs.python.org/3/library/contextvars.html](https://docs.python.org/3/library/contextvars.html)

------
Grue3
>f-strings

What happened to "explicit is better than implicit"? "Only one way to do
stuff"? One of the more baffling Python features if you ask me.

~~~
paganel
Exactly, the f-string syntax looks so close to PHP’s way of handling strings
that I’m really amazed that it managed to pass and be implemented. I mean, I
don’t see that much of a difference between

> name = ‘Jane’

> print(f”Hello, {name}”)

and PHP’s:

> $name = “Jane”;

> echo “Hello, $name”;

~~~
wongarsu
PHP has many problems, but I always considered string handling one of PHP's
strengths. Considering how PHP's string interpolation has gone mainstream I
don't seem to be the only one:

PHP:

    
    
        print("Hello, $name")
        print("Hello, ${getName()})
    

Python:

    
    
        print(f"Hello, {name}")
    

C#

    
    
        Console.WriteLine($"Hello, {name}")
    

Javascript

    
    
        Console.Log(`Hello, ${name}`)
    

Ruby

    
    
        puts "Hello, #{name}"
    

etc.

~~~
ryl00
Is that really PHP's, though? It's been in shell scripts and perl for quite a
while...

~~~
wongarsu
That's an interesting question. I couldn't find any summary of the history of
string interpolation. The first version of PHP in '94 had it. Bash predates
that by 5 years and Perl by another 2, but I'm not sure about the initial
feature set of either of those. The first POSIX standard for command
interpreters is from 1992. I suspect the feature comes from early versions of
csh in the early 80s.

However I think it's fair to credit PHP with introducing generations of
programers to the idea.

~~~
mturmon
Bourne shells as early as Version 7 Unix (1979, [1]) had rather elaborate
interpolation of variables into strings (i.e., not just ${foo} but ${foo?bar},
etc.).

I'm reasonably sure that earlier versions of _sh_ had some facility for this
as well.

So, it's not really a PHP innovation, although some people might have seen it
first there.

[1] [https://www.in-ulm.de/~mascheck/bourne/v7/](https://www.in-
ulm.de/~mascheck/bourne/v7/) -> "Parameter substitution"

~~~
wongarsu
Apparently Unix Version 6 (1975) used Thompson Shell which (provided the
manuals are correct [1][2]) didn't support arbitrary variables (and even
environment variables were not a thing back then). However for use in scripts
$0, $1, etc were replaces with the script name and the arguments.

1: [https://www.in-ulm.de/~mascheck/bourne/v6/](https://www.in-
ulm.de/~mascheck/bourne/v6/)

2: [https://etsh.nl/man/_tsh.1.html](https://etsh.nl/man/_tsh.1.html)

------
croh
1\. f-string and extended-iterable-unpacking reminds ruby. i was really
missing them.

2\. pathlib is cool. will come pretty handy.

3\. Data classes sounds good but there should be only one way to do things,
even you end up writing few more lines.

4\. type-hints are ok for very very big projects.

5\. No comment on implicit-namespace-packages yet as still trying to
understand solid use-case.

~~~
DonaldPShimoda
> Data classes sounds good but there should be only one way to do things

Dataclasses greatly simplify generation of simple classes which are
unnecessarily filled with boilerplate. I'd argue that they _are_ the one way
to do this, and that choosing to manually implement the same naive `__init__`
function for every _simple_ class you write is the "wrong" way.

(Here I take "simple class" to mean a class which takes in some values during
initialization and stores them without anything terribly interesting going on
during that initialization. A simple class can have methods defined on it,
though.)

> type-hints are ok for very very big projects.

D:

> No comment on implicit-namespace-packages yet as still trying to understand
> solid use-case.

I think it's just... trying to keep your directories "clean"? I also don't
really understand the use of this haha.

~~~
croh
> Dataclasses greatly simplify generation of simple classes which are
> unnecessarily filled with boilerplate

I would love to solve these boilerplate kinds of problems using plugging like
emmets. Magic like this feels good when writing but troubles during debugging
and customizing.

Additionally naive programmers always use such features in wrong situation if
they don't get use-case. I really feel sad after seeing so much bad-django-
code in production.

------
yrro
importlib.resources is an excellent replacement for pkg_resources.

with importlib.resources.open_binary('my.package', 'foo.png') as f: ...

Avoids the overhead of importing pkg_resources, and hassle of having to call
cleanup_resources before the interpreter shuts down. Backports are available
for Python <= 3.6 too!

------
baseballMan
I'm by no means a hardcore python dev but I feel like these are all pretty
basic, common things. No?

~~~
jedberg
They're basic but also things you'd never look up, especially if you've been
doing python a long time.

For example, I just learned about f strings, because why would I need to ever
look up if there is a replacement for .format()?

And the LRU cache. I've been hand rolling that for years, but I never thought
to see if they had added it to the standard library, because why would I look?

~~~
mixmastamyk
It pays to look thru the stdlib every so often, there is just so much there,
and plenty of dark corners (in the Warcraft sense) to look in.

I hand rolled stuff in itertools/functools for years before discovering
them.... collections Counter, etc.

Or how about str.partition instead of try: str.split() ?

~~~
Twirrim
On a related note, every couple of years I make an effort to man page every
cli tool I use, and re-read the man page, just in case. Most times I discover
there is some argument that I've missed before in a tool (or has been added in
the intervening time)

~~~
jedberg
When my dad sold cars he’d always tell his customers to read the car manual
again after six months for the same reason.

------
iandanforth
TIL - Enum, auto(), @dataclass, and that classes don't need (object) anymore.
Neat!

~~~
DonaldPShimoda
EDIT: nope, nope, this is all wrong. My mistake. Ignore everything else here.

> classes don't need (object) anymore

My friend, old-style classes became unnecessary with the release of Python 2.2
— almost 20 years ago now [0]. I'm afraid you've been living in the past. :)

[0]
[https://wiki.python.org/moin/NewClassVsClassicClass](https://wiki.python.org/moin/NewClassVsClassicClass)

~~~
nerdwaller
Extending `object` was necessary until 2.7 when it became the default and old
style classes were removed entirely in 3. So I think while the GP comment
recently learned they don’t need to extend `object` anymore, they are/were
familiar with new style vs old style classes.

~~~
auscompgeek
New-style classes never became the default in Python 2:

    
    
        Python 2.7.15 (default, Jun 27 2018, 13:05:28) 
        [GCC 8.1.1 20180531] on linux2
        Type "help", "copyright", "credits" or "license" for more information.
        >>> class Foo:
        ...   pass
        ... 
        >>> Foo
        <class __main__.Foo at 0x6218e384ee88>
        >>> class Bar(object):
        ...   pass
        ... 
        >>> Bar
        <class '__main__.Bar'>
        >>> isinstance(Bar, type)
        True
        >>> isinstance(Foo, type)
        False

~~~
nerdwaller
Thank you for the correction! I’ve not used Py2 in 6 or so years.

------
chrshawkes
You can now use Python Scrapy with the latest versions of Python 3 for web
scraping. Here's an example
[https://youtu.be/qj6H38Xwvu0](https://youtu.be/qj6H38Xwvu0)

It even works on Windows.

------
Areading314
I would add to this list:

    
    
      * generators
      * defaultdict
      * generators
      * sets

~~~
mythrwy
Generators and sets have been around for a long time I think.

They were there in 2.X version like 9-10 years ago when I first used Python
anyway and aren't 3 specific.

~~~
jwilk
Generators were added in Python 2.2:
[https://docs.python.org/2/whatsnew/2.2.html#pep-255-simple-g...](https://docs.python.org/2/whatsnew/2.2.html#pep-255-simple-
generators)

Built-in set objects were added in Python 2.4:
[https://docs.python.org/2/whatsnew/2.4.html#pep-218-built-
in...](https://docs.python.org/2/whatsnew/2.4.html#pep-218-built-in-set-
objects)

defaultdict was added in Python 2.5:
[https://docs.python.org/2/library/collections.html#collectio...](https://docs.python.org/2/library/collections.html#collections.defaultdict)

------
dopeboy
Is type hinting being adopted by Pythonistas today? I've been aware of the
feature but haven't used it. To be a modern Python programmer, should I start
using it?

~~~
DonaldPShimoda
I use it everywhere because it vastly improves code readability/usability in
my IDE (PyCharm). But I don't know if I'm representative of the general Python
population.

------
reacharavindh
I was curious to see how asyncio has matured into such a list.. but it was
missing the list. Is it common enough for people to use in scripts to speed up
concurrent work yet?

~~~
dagw
Anecdotally, no. From where I sit, the multiprocessing and threading modules
still seem to be the main way to to concurrency in python.

~~~
nurettin
From where I sit (I've been soloing python projects for a few months now) For
IO-blocking tasks, asyncio is the way to go and threading is very rarely
needed if any. It is very simple to place a bunch of tasks into a list and do
asyncio.gather on them, or add timeouts to async methods.

For CPU intensive tasks, asyncio actually provides it's own syntax for process
pools which are easily interchangeable with thread pools (just change an
import alias)

~~~
ozychhi
We actually tried switching to asyncio in production, but got worse cpu
utilisation and worse latency (vs greenlet). After some benchmarking and
tuning, we got a bit better latency, but CPU utilisation was still worse, so
we actually ended up swithcing back to just using greenlet :(

~~~
nurettin
I would not recommend using asyncio for cpu-intensive tasks. Processing pools
are much better for that.

------
brootstrap
Not sure anyone will see this but this article is partly trash. When your post
is titled "things you are not using in python3 but probably should" and the
first section is on f-strings... I was tempted to close the tab then , but i
followed thru and did find some interesting things.

But seriously f-strings? people have been talking about these for years now,
it's not new is it?

~~~
DonaldPShimoda
If you look through the other comments here, you'll find plenty of people who
didn't know about f-strings prior to this article.

------
schemathings
I didn't start using python til 3, but list comprehensions and f-strings are
great. I've really been enjoying the coding style.

------
techno_modus
Here is another short guide on many useful features of Python 3:
[https://github.com/arogozhnikov/python3_with_pleasure](https://github.com/arogozhnikov/python3_with_pleasure)

------
Already__Taken
I really hate that __init__.py thing about modules it confuses the F out of
teachers and students. Using files without a "program" on the command line is
a massive leap as it is.

------
teekert
I read quite some things about the data class... in short: If I use a lot of
pandas.DataFrames, is this something I should learn about?

~~~
krapht
No. Data classes are a mutable replacement for collections.namedtuple.

~~~
teekert
Thanx!

------
dorfsmay
How do you define class variable in a data class?

~~~
ericvsmith
typing.ClassVar. See
[https://docs.python.org/3/library/dataclasses.html#class-
var...](https://docs.python.org/3/library/dataclasses.html#class-variables)

------
vedyou
Thanks for all these.

------
speedplane
There's no reason why Python 2 can't have the vast majority of these features.
It's a shame that the Python continues to ignore the reality of the mess they
made with Python 3, and failing to question what was an originally bad idea.

~~~
xxpor
This question is done and dusted. There's literally no point in discussing it
any more. CPython 2.7 support ends in 7 months. It's time to move on.

~~~
speedplane
> There's literally no point in discussing it any more. CPython 2.7 support
> ends in 7 months. It's time to move on.

Ah, the classic "nothing to see here, keep moving on" argument. The lack of
admission of a bad idea is itself a problem. What happens in a few years when
Python 4 renders all Python 3 code incompatible?

~~~
DonaldPShimoda
> What happens in a few years when Python 4 renders all Python 3 code
> incompatible?

Ah, the classic "they did it once so they'll definitely do it every single
time from now on" argument.

Nick Coghlan, one of the Python core developers, said "Python 4.0 will merely
be "the release that comes after Python 3.9"" [0], so I think your concerns
are ill-based.

[0]
[https://www.curiousefficiency.org/posts/2014/08/python-4000....](https://www.curiousefficiency.org/posts/2014/08/python-4000.html)

~~~
mixmastamyk
Not to mention some of us are glad lots of things got fixed and not sore in
the slightest.

~~~
speedplane
> Not to mention some of us are glad lots of things got fixed and not sore in
> the slightest.

The people who are not "sore in the slightest" probably don't have to deal
with large Python 2 codebases that rely on libraries that have no plan to move
to Python 3. They are typically people who are writing code from scratch.

Rendering a huge codebase obsolete in order to upgrade print statements,
import statements, and internationalization (i.e., unicode) was not a fair
trade for many existing projects.

~~~
mixmastamyk
Been writing Python since roughly 2000.

My stuff was not overly concerned with encodings, that part was luck. I moved
to the logging module early, avoiding print problems, that was smart. Other
changes were trivial mechanical fixes, that was easy.

For the unlucky, obtuse, or resource challenged, you've had an extra ten years
of support. That's sufficient IMHO. It is time to suck it up and port, or
retire the app. Constant bitching just gets old.

Meanwhile, I'm using a great language that will be relevant for years.

