 Hi everyone, my name is Victor Stiner and I'm going to present you Python 3 10 years later. So I'm a C Python core developer for eight years, but I'm contributing to Python for 10 years. Currently I'm working on C Python on OpenStack for Red Hat, but I moved to a new team recently, so today I do maintain Python for Red Hat, and I'm a very happy user of Fedora on them. I decided to organize my talk in four parts, the four seasons, so let's start with Outone. So the start of Python 3 was a project called Python 3000, and everything started with a PEP written in 2006, the Python 3000, and the thing is that at this time more and more people started to complain about things called Python warts, which are design issue of Python 2, and some people started to write a list of all the warts, so the plan was to fix all of them, or most of them. To give you some example, in Python 2 you have two different types for integers, you have the long integer and small integer, and depending on the operation, depending on the input type, you may get a small or large or long integer, so if you would like to test the type for variable to check if it's an integer, you have to check for both types, and if you're new in Python, it could be very surprising to have two different types for the same thing. And something else is that we added a new class in Python 2 during the development on Python 2, so for example, add properties, and the issue with the new class is that if you use new features like properties on all class, it doesn't work as expected. And again, it's a little bit confusing, that's depending if you inherit from object or not, you get an old or new class. So the idea was to move to the new class and just remove the old one. For example, when you divide two integers in Python, you get an integer in Python 2, and when you are new to Python or when you use a calculator, you expect that you get a floating point number. For example, divide 1 by 2, you get 0 in Python 2, and it's maybe not the expected results. So we wanted to change that to always return a float, especially because in Python 2 you already have a dedicated operator, which is the integer division. Instead of a single slash, it's a double slash to always get an integer. For Unicode, I would say that if your application is using Unicode everywhere, like for inputs, for outputs, if all the text is on proceed as Unicode, everything is fine. If all your inputs are bytes, all the outputs are bytes, you get bytes everywhere, everything is fine. But if you have both Unicode and bytes, you will get a hard time because it works in most cases, but as soon as you write a name with a non-asky character, like a letter with a diacritic in French, you get a Unicode error, and it can be very painful to fix all your application to make sure that you are using Unicode everywhere. So we also wanted to change that in Python 3. For the comparison in Python 2, the idea is that the comparison never fails. So if you compare two numbers, if you compare two objects, but your Python is not able to compare the two objects, what Python does is to get the type, the name of the type of the object. For example, you compare the number 3 to the string hello, you get the string int for integer and the string s tier for the name of the type, and Python decides to order this object depending on the two strings. It's a little bit surprising, and maybe not the behavior that you expected, so again, we wanted to change that. And last but not least, in Python 2, all imports are relative by default. So if you use the same name that the module in the Stornart library, like the CIS module or the OS module, you may get your own code instead of the module from the Stornart library. So it can be very surprising, and you can get a lot of issues depending on how you run your application. So again, we wanted to change that to use the imports absolute by default. To limit the risk, to not break everything, from the very beginning of Python 3, the idea was to only fix acknowledged watts, to not fix everything, but a short list of things. We also had a community process to decide what to change, which means that we have a list of peps with numbers starting with 3,000. And we did not want to re-implement the interpreter from scratch. The interpreter is a C Python, which is written in the C language. And if you write a new implementation, maybe what you can get is to get a very subtle behavior changes between Python 2 and Python 3. And the idea was to limit the number of changes, to really make sure that we get the best backward compatibility. And from the very beginning of Python 2, Python 3, sorry, we already had a deadline for the end of life for Python 2 to warn all of your users to make sure that everybody is aware that we are moving on, and it's time to move to the new Python. And finally, in 2008, the Holy Grail, Python 3, we got it. And the first migration plan was very, very simple. Python 3 comes with an application called 2-3 to port your whole code base that wants to Python 2, from Python 2 to Python 3. And by doing that, it's very easy because it's a single step and you're done. Maybe if I'm still here to discuss about the migration from Python 2 to Python 3, maybe it didn't go as expected because there are many reasons why it doesn't work as smooth as expected. And one of the issues is that when Python 3 was being released on Linux, you didn't get Python 3 from the first day. We had to wait one up to two years to get Python 3 in Linux. So if you remove the Python 2 supports, you drop all your user base. If your user base is in Linux. So for the maintenance of modules, using 2 to 3 was a no-go because we just don't want to lose our users. Another issue with this migration plan is that when you have 10 dependencies, if you have a single dependency which is not compatible with Python 3, you are stuck because just, for example, import the module, raise the syntax error, and you cannot continue to port the rest of the code because you are blocked very early in the migration. And the last point is that we didn't expect that. In fact, many people were using Python 2 and we were not aware that so many people depend on the Python 2 and use it in production. And something else is that is a thing called technical depth. So let's imagine that you are a developer and you are discussing your manager and your manager asks, why should I let you work on Python 3 supports? And the developer says, for all these new cool Python 3 feeders, obviously. Okay, but can we use all these new feeders and the developer? Well, since we still have to support Python 2, nope. Because the thing is that when you still support Python 2, if you use a new feature of Python 3, you get an import error or you get a syntax error or whatever else. So it means that even if technically you support Python 3, you cannot use new features. So the migration as a cost, because you have to spend time on the migration, but there is no direct benefits. So when you discuss with a manager to explain the technical depth, it's very hard to convince your manager. So to support your code, what you can do is to divide your code in two different branches in Git or Merkle or whatever you want, to have one branch for Python 2 and one branch for Python 3. And some project decided to be forked to not have two different branch but two different repositories. In some cases, the fork was made upstream, like the DNS Python project has been forked as DNS Python 3. Sometimes the company behind the project, like PIL, didn't care about Python 3 because of the technical depth and because of the cost of the migration. So in that case, the community decided to fork the project and to actually do the migration. So the PIL project has been forked under a new name, which is PILO. And not only you get the Python 3 support but also new features. And suddenly, in some cases, the project, like, for example, MySQL Python was no longer maintained. And when I was working on OpenStack to port OpenStack to Python 3, it was a blocker issue because MySQL is very popular in OpenStack. And this was the only driver to connect to the database. And since the project was no longer maintained, it was very difficult to get any change merge in the official project. So one guy decided to fork the project under a new name, MySQL clients, to port to Python 3 and again to add new features to fix bugs. But you got a new issue is that you don't know what is official upstream because the old one is official one but it's no longer maintained. And if you move to the new one, you don't know if the old maintainer will maybe wake up one day and say, oh, this is my project. You stole my project. It was a little bit difficult in some cases. And when Python 3 has been released, the stable version of Python 2 was still Python 2.6. And the issue with Python 2.6 is that it has a lot of troubles to write a single code base for Python 2 and Python 3 in the same file because of the syntax, it didn't help to write a single code base. For example, about the Unicode string in Python 2 to get a Unicode string, you have the U prefix. But if you use this U prefix in Python 3.0, you get a syntax error because we decided that it doesn't make sense in Python 3 to have a prefix because by default everything is Unicode. So you don't have to add any prefix. It's obvious. This was not a good choice because people really wanted to keep Python 2 support. So it was very painful. And one solution was the 6th module, which has a U function. And when you call this function, depending if it is Python 2 or Python 3, you get a conversion, like you decode the string to get Unicode on Python 3. And then in Python 2, if you really wanted to get Python 3 features like the new Unitest, which has new methods to write Unitest, you can use a backported version of the module. But then it's a pain because you have to pull a dependency and it's more complicated than using something for the standard library. So after the autumn comes the cold time of the winter time. And to start the winter, there is a website which has been created in 2011 which is called Python 3 Wall of Shame. And the purpose of the website was not really to blame maintainer. The intent was to motivate package maintainer to move on to Python 3. But when the website has been created, only 9% of the top 200 projects on PyPI were compatible with Python 3. And to give you an idea of the status of the migration at the beginning, I identified three big players in the Python community which are Twisted, Mercurial and Django. Twisted is a very powerful framework to write network applications, not only clients but also servers. Mercurial is something similar to Git. It's a source control management and it's written fully in Python. The last one, Django, maybe you already heard about it. It's a very popular framework to write web application, to have the database using an ORAM, to have templating, to manage users, to generate the admin interface. So it's a very complete framework and it's very popular. But when Python 3 has been released, there were some troubles to bought all these applications to Python 3. The issue with Twisted on Mercurial is that Twisted is working on the network layer. On the network, you cannot speak Unicode because you only have wires, you have bytes, and to get Unicode there, I would say it's not the appropriate type to manage network. So the native type for Twisted is not Unicode but bytes. And Python 3 makes it more difficult to use bytes. And for Mercurial, it's the same thing because not only for the file contents but also for the file name, they really wanted to use bytes to get the best compatibility with all operating systems. And because of that, it was a very long journey to them to be ported to Python 3. For example, Twisted today is ported but Mercurial is still a work in progress, 10 years later. And Django, at the beginning, it supported Unicode but it was not perfect. There were many, many issues. So it took time to port Django to Python 3. And because of all this issue that I started to describe, because of the very slow migration, because of all these problems, we started to see the French guy, the Python 3 trolls. We considered that maybe Python 3 doesn't bring anything because as I explained, when you use Python 3, you cannot use new features because you still have to support Python 2. So you have to spend a lot of time for the migration but you don't get anything. So what's the point of Python 3? It's useless. And according to the trolls, the migration to Unicode is just a pain point. It doesn't bring anything because if you use bytes in Python 2, you never get any kind of error because of Unicode error or Unicode encoder error because bytes just works. Maybe if you use two different documents in two different encodings, your maids get an error but not an error but mojibake, which means that you get strange letters in your text, but they say that, oh, who cares? We all speak English. So slowly the trolls come up with a new idea. They say, hmm, maybe people are still using Python 2. Maybe we should just continue the development on Python 2 and let the core developers do the same thing on Python 3. And so they decided to create Python 2.8, which is a Python 2.7 with new features. And the problem was that even if some people were like the idea, nobody was volunteer to do the actual work. And to give you an idea of this issue is that in 2014, so it's only four years ago, there was still a debate about the transitional Python 2.8. And what was written in this article is that they are still concerned about Python 3, which may never take off. And Python 3 only represents under 2% of packages according to the trolls. But what we did in 2011 is to write a PEP, the PEP 4.0, the PEP not found, which is the Python 2.8 on release scale. It's a document to explain that, no, we are not going to continue the development in Python 2. We have very good reason to move on. And it's a document to make it very obvious for everyone. And if you look at the numbers differently, in 2013, in fact, 80% of the most of the 50 top projects on PyPI were already compatible with Python 3. So it was not 2%, but 80, it's different. And in 2014, at the PyCon US, Willow Van Rossum gave a keynote, and he took a very, very good, wise decision. We decided to extend the support of Python 2 by 5 years. It means that instead of having a usual support of 5 years, we get a very long support of 10 years. And the idea was to send a message to all our Python 2 users to say that, okay, we know that you have good reason to not migrate right now. I took time to migrate the dependency, took time to write new tools. We know that it's very painful. We will not break Python 2. For your information today, Python 2 still gets security fixes. It still gets bug fixes. You still get new release at least once a year. So we still support Python 2. We don't force you to move right now. There is no intent to break Python 2 on purpose. So the deadline is now in 2 years. So after the cold winter comes the fresh air of the spring with flowers, new plants, some new starts. The good news is that we fixed our first issue in Python. Do you know what is the first issue in Python? The first issue was that when you are to install a dependency, the newcomer came on IRC on a main line and asked, how can I install a dependency? And the answer was, oh, just install setup tools. Okay, but how can I install setup tools? So you had to go to a specific website, download a Python script, install the Python script, and maybe you need a system administrator permission to install the script. So it was very painful to explain how to install your first dependency. And the good news is that in 2011, PIP 1.0 has been released. And in Python 3.7.9 and Python 3.4, we added something called Ensure PIP. So it's not PIP itself, but it is the thing to bootstrap PIP. It's an installer of PIP. So thanks to that now, you don't have to worry about how to install PIP because it's already part of the language. You already have something to install PIP for you. You don't have to take care of that. And because of Ensure PIP has been added to the standard library, quickly PIP became the de facto installer for Python. So because of that, today you don't have to ask how to install something. Everybody knows that it's PIP. And thanks to that, it's much more easier to install dependency and it's also much more easier to have dependencies because previously some people just didn't want to have dependency as they decided to vendor some libraries to avoid any kind of dependency. And out of that, you get some security issues, for example. And the last point is that today, Linux distribution also comes with PIP. Okay, so previously I said that maybe two to three was not as a good approach for the migration because you just lose all your Python 2 users. So maybe we can do something differently that instead of removing Python 2 support, is to add the Python 3 support. And said like that, it seems very obvious because people know today how to do that. But you have to understand that it took a lot of time to came up to this new approach because it took a lot of time to understand that the old approach was wrong. It also took time to write the new tools to do actually the migration. And there are very important modules like 6, for example. 6 is very useful to write a single code base for Python 2 and Python 3. And one example of this new approach is a modernized tool which takes your Python 2 code base and adds Python 3 support. And I also wrote a different tool which is called 6r. This tool is written for my very own usage which is to port OpenStack to Python 3 because in OpenStack it's a giant project with 2,000 developers, a lot of companies, many, many things, many changes are merged every day. So if you generate a giant patch, you can be sure that in a few hours you will get a conflict. So I wrote a new tool to be able to modify only a few files by doing a few specific operations. For example, using my tool, you can only add parentheses to the print statement to convert the statement to a function call because the function calls works on Python 2 and Python 3. And by doing that, the main benefit is that instead of porting your code base at once, in fact, you can do it step by step. And by doing that, you can validate that at each step everything is fine. You can run tests to check that there is no relation. And it's much easier to review these changes because they are much shorter. So thanks to this approach, it was much more easier to port big applications. If you are a very big company, maybe you get other issues because your code base is really large. In this case, maybe you need a different approach. For example, for very old legacy code, what you can do is to first add new tests because nobody wants to get regression just because of Python 3. So the idea is that first you write tests to make sure that you don't regress. And another approach tested by Dropbox is that they are working on type hinting, type annotation. And using the typing module, which is new in Python 3.5, I think, you can standardize the way to annotate the type for function parameters and for the residual type. And by doing that, you can use a tool called MyPy, which is a static analyzer to make sure that you pass the correct type to a function. And by doing that, they expect that the migration to Python 3 would be much, much more easier. And to make the transition easier, we have also made changes in both sides of Python. For example, in Python 3.3, we reintroduced the Euro prefix for string. And thanks to that, you can use the prefix in Python 2 and Python 3 to get a single code base with unique code strings. In 3.5, we added the bytes formatting operator, bytes percent args. This is very useful for Mercurial and Twisted because they manipulate a lot of bytes. And the bytes operator is more efficient than taking bytes, conversing with unique code and encode bytes back to bytes. And on the Python 2 sides, what we did is also to add new warnings. The idea of warning is that you take your application, you enable the warning, and once you get a warning, you know that, oh, maybe you should have a look at this part of the code, and you can start to fix some issues which are warnings about future backward-uncompatible changes. And again, to build bridges between the two versions, more and more people back-ported Python 3 features from Python 3 to Python 2, which means that, actually, you can use Python 3 features. So, for example, there is a unit test tool, but also Enum 3.4, which is a new Enum module of Python 3.4. And after spring comes the summertime. If you recall, the website called Python 3 Wall of Shame, the author of the website changed the title to Wall of Superpower. Yeah! I removed from 9% to 95%. So, it's almost 100%. But in practice, you have to know that we don't need 100% for the top 200 packages, because this list is very long, and in the list, you have some packages which have been deprecated and replaced by better solutions. And another very good news is that, finally, Python 3 is faster than Python 2. On this picture, you can see that on a specific list of benchmarks, the list of benchmarks where Python 3 is the difference with Python 3 is the most significant. So, all results are normalized to Python 2, and if a line is smaller, it means that it's way faster. So, you can see that in some cases, it's up to two times faster or even faster. So, there are just two cases where Python 3 is still slower. It's a start-up time. So, there are two benchmarks for the time-to-start-up Python. This is an issue when you have a very short command-line interface. Just run a command and get a result immediately. But we are working on these issues. To explain it differently, you have to know that the Instagram company is fully based on Python, because Instagram is using Django. And because of the time-to-market, it's not possible for them to rewrite everything in a different language or just to rewrite everything from scratch because there are too many competitors on this market. So, what they did is to post their code days from Python 2 to Python 3. And just by doing that, now they saved 12% of the CPU and 30% of memory. And if you think about a very, very large company with Instagram with 700 million users, it costs a lot for the server because they need a lot of servers. So, any kind of optimization means a lot of money for them. If you did not look at Python 3 changes and you are still not convinced to move to Python 3, maybe you have to know that we have a list of bugs that cannot be fixed in Python 2. Because Python 2 is very old and because it's very old, we know more and more bugs. But we cannot fix these bugs because of the backward compatibility because people consider that Python 2.7 will never change and they have expectations on that. We will not break the change of behavior. But sometimes to fix bugs, you really have to break the backward compatibility. For example, if you think about Unicode, technically we can do a lot of things in Python 2. We can break the backward compatibility to make sure that when you compare bytes to a Unicode, you get an error. But if you do that, you can be sure that many users will complain because it will just break all applications written in Python 2. Another issue is that for the dictionary type in Python 2, we are using an hash function because it's an array with an hash function to implement the dictionary. And if you inject specific strings, you get the worst case complexity, which means that Python becomes very, very slow. And this is a security issue if you have a web application because an attacker is able to crash your server to abuse your CPU. And we fix the issue in Python 2, but the fix cannot be enabled by default because it changes the order of elements in a dictionary. So if you really want to make sure that you are secure, you have to opt in for the new fix. To give you another example, the sub-process module to spawn sub-process, it is not thread safe. So maybe you did not notice because everything is fine, but maybe one day during the night you will get this bug and you will add a bad time because it's very difficult to work around this issue. You need to put a lock on the function and if you have a big code base, it can take a lot of time to fix the issue everywhere. And there are even more complex issues like the recursive lock in Python 2 is not signal safe. So imagine that you spawn a child process. When the child process completes, you get a signal to notify that the child process completes. And this signal, if it comes at the wrong time, can make your recursive lock inconsistent. So that thing will happen. And you cannot control when it happens. It's very difficult to reproduce this kind of bug because you don't control the execution time of the child process. So you may get the signal early or late. And last but not least, as the clocks in Python 2 are not monotonic. If you see the previous talk about the time zone, you also see that you have the winter time and a summer time in many countries. And even in some countries, you get four changes per year. And because of the change, the clock moves in one direction or another by one hour. And in some cases, it can crash your application because the application doesn't understand why the clock is moving backward or forward. And to fix this issue, you need a monotonic lock, but we were not able to fix that issue in Python 2. But the good news is that we fixed everything. So just use the Python 3 on your goods. For example, I added a monotonic lock in 3.3. And one more complex change is that file descriptor. It's a file descriptor. You can imagine it's a file. By default, in Python 2, when you spawn a child process, you will inherit all open files. It means that if you open a list of passwords in the master process and you spawn a new application, you will be able to access the password files and you may not expect this behavior. And it was very difficult to convince other core developers that it's not a good idea because this change breaks the backward compatibility and you may know that we care a lot about the backward compatibility. In Python 3.7, I made a different change is that when you get a signal, for example, when a child process completes, when you get a signal, Python is currently blocked in a blocking C-scroll. So for example, you read data on the disk, and the disk doesn't have the data in cache, so you have to wait for the hardware. In this case, if you get a signal, the C-scroll is interrupted. You get an interrupted error. And in this case, you may get an error and you have to handle it in your application. And it's very annoying because you have to be prepared for signal at any kind of C-scroll and there are many, many blocking C-scrolls. So the change is that Python will now retry the C-scroll for you. So if you are blocking C-scroll and you get this error, Python will just do the same C-scroll one more time. And so to explain you the advantage of Python 3 is that this is a quote from Widow Van Rossoom on my pep about the file descriptors. He wrote that we are aware of the code breakage. This is likely to cross, but doing it anyway for the good of mankind. And if you're still stuck at Python 2 and you still need reason to move to Python 3, you have to know that in the standard library we got not less than 21 new modules. And just to name a few, there is a asyncio, enum, passlib, unites.mock and many, many others. So it means that you don't have to install them. They are already part of Python. And it's very useful to develop new application. It will use a number of dependencies and there are some tools, for example, to debug Python, which are very useful. So not only is the Python has new features in the standard library, but the Python language itself also evolved. For example, one popular features of Python 3.6 is called fString. It's a new way to format string. And in my opinion, it's just the best way to format string because it's very short, it's very obvious, and it's very difficult to make mistakes. For example, you can just name a variable and the variable is replaced by its value, but you can also call a method on an object, like call the title method to convert the first letter to an uppercase. You can even do any kind of Python expression. So you can do a lot of things and not only you can use it for prints, but also for any kind of string. For asynchronous programming, we added a lot of things for Python 3 coroutines. The first challenge was to add a yield from, which is something to delegate generator. This means that you have one generator and you pass through all values to a different generator. And the first version of, I think, I used yield from, but it was a little bit surprising to use it. So in Python 3.5, we added two new keywords. I think to mark that one function is asynchronous and await is a keyword to say that, oh, I am waiting for something. And by doing that, it's much more obvious when you read the sentence in English that it makes sense. Not only you are about to, I think you also have something called asynchronous generators. So you can now use the yield keywords inside AsyncDef. So this is, for example, very useful if you think about a database. You would like to provide a generator to iterate on each line of a database, but you don't know if the color is going to use all lines because, for example, if you have one million of rows, you don't want to send it as a list because it will use too much memory. But using the yield, you are able to, for example, fetch 10 values and iterate on these values, and after that, fetch 10 or more values. So you can implement very efficient strategies for a database. And the Async4 can be used for an asynchronous list comprehension. Or you can also use Async inside these comprehensions. It's not only about AsyncIos, there are other very useful Python 3 features in the learn syntax. I really like the first one, which is the keyword only. So imagine that you have an existing module, it's very stable, but you need to add something to pass a new argument, but if you add a positional argument, maybe a user of your library on the old version will pass the argument and get an error. So the idea is that using a keyword only, you have to specify the name of the parameter to write keyword only equal the value. And the print statement becomes a function. So here is an example where you can use keywords, but they are not keyword only, but you give you an idea of the syntax. And I also like the print function, because today you can use it in a lambda function, for example. And I really prefer the new syntax. For the star previously, you was able to use the star when you define a function to write star arguments to get an arbitrary number of arguments. But now you can also use when you assign a variable to say, for example, one star tail, and the tail gets the rest of the list, the tail of the list. And another thing is that now you can use the star inside a list, but also a double star inside a dictionary to say that you update the dictionary with another dictionary, like you concatenate two different dictionaries. And something very trivial but very, very useful for the readability of your application is that today you can add an underscore in your literal numbers. This is very useful for the readability because if you get nine zeros or six zeros, it's very difficult to read this number to see quickly if it's one million, ten million, or one billion. You can also annotate the type of a variable using colon and the name of the type, like x colon int. For the context manager, you can specify multiple context managers on a single line. This is very useful. As I said previously, there is a byte formatter to format a byte string. And something very useful if you use the numpy, it's dot operator, the at operator. It's used for matrix and multiplication. In numpy, currently the name is numpy.dot, but the issue with numpy.dot is the way that you pass arguments. It's more difficult to read the expression. Using an if fix operator, it's much more obvious how you write your formula. Okay, so we saw that the Python 3 is much more powerful. We saw that we have tooling to migrate your code very easily to Python 3. So now the question becomes, is it time to bury Python 2 to just delete it? The good news is that we already started to remove Python 2 For example, if you install a recent version of Fedora, Fedora since three years, or if you install the latest version of Ubuntu, like Ubuntu since last year, there is no Python 2 in the base system. This means that you install the full system. There is no Python binary. There is no Python 2 binary. But obviously, if you install an old application which depends on Python 2, for example, Mercurial or GIMP, the plugins written in Python, you pull the Python 2 dependency. But at least you are able to get a base system with everything in pure Python 2. About the timeline for the removal of Python 2 in projects, there is a website called Python 3 Statements. It's a timeline of 20 or more projects with the first support of Python 3 in the project, the deprecation of Python 2 and the removal of Python 2 support. And you already have Python 3 only applications, which are Django 2 and IPython 6, which are Python 3 only. And I think that Python 2 was a big achievement for the Python community because Django is a very popular module. It's very complete. It's a lot of features. And if something like Django is able to move on to Python 3, it means that any of you is able to move to Python 3. And there is also a pythonclog.org, which is a countdown until 2020, the 1st of July, which is the end of life for Python 2. So I'm working for Red Hat. So the question is also about Red Hat Enterprise Linux. You have to know that even if you use Red Hat 6 or Red Hat 7, you can already get Python 3 using something called Software Collections. It's a new repository and you can easily install, I think, Python 3.6 for Red Hat 7 and Python 3.5 for Red Hat 6. So it's already in the available and you also get supports. The support is a little bit shorter than the operating system, but it's between three years and five years. And the very good news is also that in the latest version of Red Hat Enterprise Linux, so the version 3.7, we announced that Python 2 is now deprecated. So if you need a reason to motivate your manager, you can say that even Red Hat started to deprecate Python 2. And the very good news is that the next version of Red Hat Enterprise Linux will be Python 3 only, no Python 2. And one open question to finish is that we saw that we spent a lot of time on porting all the application. It was very painful for the community. It took a lot of time and energy to write single code base for both versions. So maybe we can imagine a new approach to add new features to Python. For example, if you look at the JavaScript approach, what they did is that there are two projects called Babel on Polyfill. And using this project, you are able to use the new version of JavaScript, even on very old browsers. And by doing that, JavaScript is able to evolve very quickly, much more faster than Python. By evolving, I mean that you can use the new features. You don't have to wait until all browsers around the world move to the latest version of JavaScript. And I suggest you to see the talk of Daniel Espotti at PyCon Italy. He describes the evolution or stagnation of programming languages, and he compared Python to JavaScript. Mm-hmm. Okay. Okay, seriously, about Python 4. I know that many, many of you are joking about Python 4 and expect that Python 4 would be the new Python 3 to break the world again. I think that everybody understood that Python 3 was not well-prepared, and maybe for the next version of Python 4 we will do it very, very differently. I mean that my expectation for the Python 4 is that it will be as any release of Python 3, which means that we follow the same deprecation process. We don't remove features just for fun. We will not break the compatibility for free. We will just follow the usual process, which is that at least you have one version with a deprecation warning, and sometimes you even have a pending deprecation warning, another version with a deprecation warning, until at the third version you start to remove the function. So my expectation is that it will be just as any other release. Okay, thank you. So we can do maybe one quick question. There is a question there. Thank you for your talk. I was going to ask a boring question about process IDs and process modules, but I'll switch to a more interesting one. How do you yourself and the rest of the core team along with the PSF kind of work to get this kind of through, because you're all not in the same place, this is not in the same company? How do you decide these maybe contentious type decisions to go a certain way or do a certain thing? I'd be interested to know what's the process for getting Python out there, the thing that we all use every day. So your question is about how we take decision in Python to accept a feature or not. So I've noticed the ES6 is starting to look a lot like Python with the imports, and Python now with the f-string looks like ES6. So how has that process kind of started to work? What I like in Python is that compared to Java, the Java world, for example, everything is open to everyone. There is a Python ID's mailing list when you can propose IDs to get a first feedback. And once the ID is mature enough, it moves to Python Dev where we get a second discussion. And it seems like anyone is able to propose IDs, and if the ID is good enough, you may decide to implement it yourself or find someone else. And I don't think that Python is owned by any companies. I think that it's more a community process, and I don't recall that one company forced to get one specific issue. And as I said, it's really, for me, it's a power of the Python community to be open and not to restrict. You don't have to subscribe or pay money to propose new IDs. And for the decision itself, again, it's driven by the community. Maybe some of you have heard about a new operator, which is called Equal, the PEP 7572. It's a new assignment operator. I think that we got something like 800 emails about stats. So we got a lot, a lot of discussion. And this is an example where the community stand up to say that I don't like this feature and we don't want to get it. So I think that the process works pretty well. And another aspect of the decision is also that we have the BDFR in Python with Guido van Wassen. And we also have very strict rules about the consistency of the language. And I think that one of the key responsibility of Guido is to make sure that the world language remains consistent. So if it's not Pythonic, it will not go into Python. Okay, thank you everyone. Just a round of applause for Victor.