 Bonsoir tout le monde, on va commencer? Bonsoir tout le monde, merci beaucoup pour... Bonsoir! Oui bonsoir! Désolé tout le monde! Ok, merci tout le monde d'être venu avec nous. Je suis un peu excité, fatigué et tout ça en même temps parce que je ne savais pas qu'il va vous autant de monde. Je ne sais pas pas y parler mais bon, parce que s'il y a quelque chose qui ne marche pas bien, je vais commencer tout de suite parce que la chose la plus importante c'est que d'habitude mon ami Yannick il me dit toujours ça mais je ne comprends pas trop pourquoi il dit toujours ça c'est que à Montréal-Piton on a le code de conduit. Là je comprends parce que là on est comme beaucoup de monde on veut que tout le monde s'amuse en respectant les choses, les autres. C'est un peu le code de conduit de Montréal-Piton si vous avez quelque chose que vous n'êtes pas content ou quelqu'un qui est un peu trop méchant mais vous pouvez me parler. Donc, merci tout le monde pour nous rejoindre. Je suis vraiment excité et je ne sais pas ce qu'on va dire mais j'aimerais juste dire que à Montréal-Piton on a le code de conduit donc on veut que tout le monde s'amuse mais respecte les autres. Donc si vous voyez quelque chose que ce n'est pas correct vous pouvez me parler à Israël ou à Alex. Ok, je vais arrêter de parler parce que je ne sais plus quoi dire. Je vais juste introduire tout de suite Alex qui va parler un peu de plein. C'est bon? Ok, merci. Bienvenue chez Flair. Vous êtes dans les bureaux de Flair Systems de Montréal. Flair, c'est une entreprise en cyber sécurité. On fait un SaaS en ligne qui permet aux équipes de cyber sécurité d'avoir une vue sur ce qu'on appelle leur digital footprint. Digital footprint, ça veut dire plusieurs choses. Ça veut dire les services que vous avez d'exposer sur Internet. Ça veut dire ton équipe de marketing ça veut dire des consultants qui commettent du code publiquement sur GitHub avec ton API puis ce qui se passe sur le dark web puisque les gens disent sur toi puis les mots de passe que tes employés se sont fait voler. Nous on aigle les entreprises à avoir une vue sur ces choses-là et à réagir rapidement lorsqu'il y a des problèmes. C'est le dernier Meetup qu'on a organisé. C'était post-Grace Montréal. Il y avait à peu près 20 personnes qui avaient dit qu'ils allaient venir. On a commandé la pizza pour 20 personnes. Il y avait près 4 personnes qui sont présentées. Alors aujourd'hui on s'est dit on va laisser faire pour la pizza. On s'est définitivement trompés. Si c'est un pattern qui se répète, on va définitivement s'agister pour la pizza. En réalité, merci d'être venu. On est bien contents de vous voir en si grand nombre. Tu veux quickly repeat in English. Flare Systems is a SaaS company. We provide a SaaS for cyber security teams. And what we do is we help them understand what we call their digital footprint. So this can be a number of things. So this can be your open services that are available from the web. This can be your marketing team that opened the public trial and didn't realize it. Or this can be a consultants publishing your IP on GitHub by mistakes. And what we, or even people stealing your private information and posting it on the dark web. What we do is we help cyber security teams be alerted as soon as these things happen and react ideally proactively about these things. As I was saying before, it's the last time that we hosted a meet-up. We had, it was Postgres Montreal. We had about 20 people that said they would come. It ended up being about four. And we had ordered pizza for 20, so we ate pizza the whole week. We tried to avoid the mistake this week because pizza is a larger number and we don't want to eat pizza for two weeks. But we're going to adapt next time if it's a trend that keeps the same. So welcome at Flare. And so we are always looking for new talents. So if you think what we're doing is interesting, please either talk to me, Israel, Matthew that's hiding in the back or anybody with a Flare shirt and we'll be happy to talk to you about what we're doing. So without further ado, I'll leave it to Israel, which is co-founder at Flare. Thank you, Alex. Ok, so thank you for being here. First of all, very exciting to see so many people. So my presentation today is about moving to Python 3.11. And why and how we should be doing it. So first of all, who am I? As Alex says, I'm Israel Ali. You can read my email here and my mwgd on GitHub or whatever, Israel 17. I am co-founder and chief architect at Flare. I've been working here since the very beginning. So it's like so small, I can see my slides. So yeah, so I won't repeat what Alex said, but like Flare is a sub-rescript sas product. So we are hiring, so if you are excited about what we do, please talk to us. I'm also into sub-rescript. I've been a reverse engineer in the past doing sub-rescript research pounding, seeing my batteries, thing of that. I do a lot of Python in the past for my exploit nowadays just to build products. We like this song coming out of this computer. Oh, can you mute? Just close it again. I got it. So yeah, I do a lot of Python. I saw Love Rust, just like language theory, I think it's pretty neat. And I'm a climber, so I do a lot of climbing. You might see a few pictures of climbing. Python and climbing, I can talk about ours. So going back to the talk, why bother about Python 3.11? In my opinion, it's cheaper and easier to move to Python 3.11 as soon as possible, but not too soon. I know Python 3.11 has been out for 5 or 6 months already. I'm usually a dp opinion like moving to the next Python version right away is a bit risky. The dependencies won't update right away, so it might be breakage that we can fix. But our 14 dependencies are so bugs and all. So why now? Well, it's been enough now that more dependencies has moved to Python 3.11. All the bugs, but many of them have been fixed. Right now, it's 3.11.3 as many bug fixes has been coming in. So why should you move now to Python 3.11? Whatever Python you use, it won't be maintained forever. So if you are using Python 3.7, eventually it won't be any security update for it. So you should be moving eventually to Python 3 whatever the new release is. So your dependencies are moving too. So if you use dependencies in a project, you can do the point where these dependencies won't support older Python versions. So if you stick to your old Python version you just can have an issue with your dependencies as well and the security impact from it as well. And it's just so much easier to move from Python 3.10 to 3.11 than doing 3.10 to 3.16. People are still migrating to Python 3.11 It's going to be a lot of headache. So just do it every time and you're going to save yourself a lot of pain. Also, new toys are exciting. People love to buy new iPhone or new Android phones every year. They're going to pay thousands of bucks and now we have a new Python for free every year. Just do it. You have a bunch of new features, exciting syntax, typing extension and it's just free. I'm going to go through it but Python 3.11 is much faster than the older Python and you don't have to change anything to get them. Going through the famous toys why I'm excited about Python 3.11 First of all, it's like the new exceptional toys. So they implement the first step which is fine-graining allocation and traceback. So what it does is that now when you have a traceback there's this line number now you add the small quickly line and it tells you exactly where on the line there's an issue. I can actually compare a few interactive demo with new features. Isn't it big enough? I can't see on my screen. I might just quickly adapt. So yeah here's an example of a common code we have this dictionary inside the dictionary at one point you just access some keys inside the directory inside your dictionary inside. I just found out that the mic was facing away from me so people are online. So if I run this un petit peu de code I see, I have an error. Non type object, no subscribable so I have a non type somewhere in my dictionary. But if I look at the traceback I don't have a clue of like is it repository, is that owner, is that info, is that email I have no idea at all. So what happens if I use Python 11 now I have the famous quick line so I can see my non but info is being called sorry info item is being called on the non value so I know that the non value is owner if I look at the original code yes it is owner so that's why I think these new features are very great they can save you a lot of time especially when you look at the log in production then suddenly you can re-prove the bug right away and now you can look at the log and trace back and know ok I have like clearly this value can be known so now I can just fix it by using a get or something like that and those are so this other use case I think is great is when you have let's say this code so like the street function what it does pretty much is that I have like this dictionary of vector data and I just dot product this vector but why can't happen like if my dictionary is not built the way I thought I will have an error so let's say I'm just gonna run this code so like right now it works I have my dot product of these two vectors four what will happen if I remove one key value in there so I run the same code now I have a key error but like I have so much information in stack trace that doesn't help me like I know there's a key error in Y so I have either data 1 or data 0 that might be missing and if I look at the stack trace like it's either the vector A or vector B that might have the Y missing so I have like four I need to investigate to know the error however if I use Python 3.11 now I have this quickly line so I know exactly like it's my data 1 that is missing the Y then I know it's my second vector that has the data missing the Y so like just looking at the back trace I can know either way where in my dictionary or my data I'm missing the data so yeah there's a bunch of errors that it can really tell you like if you have a bunch of division and like one is being divided by 0 it's going to tell you it's this high above the 0 so just looking at the back trace you can fix a lot of bugs you won't need to reproduce everything to be able to find exactly where it is so I think that's pretty great so that alone is where to move to Python 3.11 but that's not all there's also a new feature in exception so it's pretty useful if you want to add context to exception with honestly like wiping it in a new exception so now there's like this unknown function you just give strings you can add a description of the AR it's pretty useful to exception group which I'm going to come with some other features and just like a small note like the notes are stored in a new magic attribute called underscore notes so you can access them in your code for whatever reason and if we look at how it looks so here I have a small use case where it could be like a use case for this note add note thing so I have like this test runner that like takes a bunch of value and I run tests on them so my test if you might just answer the value I keep it simple and then I have this run test function where I execute the unit test so that could be like high test framework and then when I have a test that fail I catch the exception and what I want to do is I want to be able to add context to the AR so I want to tell what is the value that pretty much raise the exception so what I will do with Python 3.10 or before is that I will create this new test AR that takes in a new context so I create I just raise a new test AR the test fail with this specific value and then I can always attach the other exception as the cause I can raise from the other exception so if I do that it's still pretty great like before I could get a lot of value out of this I can see like oh yeah my test fail because of the false value and then I can see the original AR at the top it's great but it's not perfect I don't have an association error anymore so if I have like I'm changing the error type so if I have if I'm building an API that I want to call under API I'm kind of hiding this error with my own error which is a bit annoying like if another API will want to cache the association error we need to cache first my test error then get the cause exception and then check if the type is exactly association error or something else so if I run this code now it's much nicer because I have a single exception which is the add note thing so now I can do like before I run my test there's an exception instead of creating a new exception I just add a note to this exception which like as before like test fail with this specific test case then I can raise my exception actually here I should remove the exception because I have a single exception which is still the original exception so association error but I still have my little message down there that tells me yeah like the exception fail because of this test case so yeah it's going to be pretty useful for a test framework for I know hypothesis is like the fuzzing framework that just finds a lot of value so instead of like stopping at the first error you can just attach a note to the error add more information right away so yeah that's another nice feature of exception added with Python 3.11 and finally there's the exception group like a syntax a new syntax feature in Python actually very nice for parallel codes like when you run many functions in parallel and some of them might fail before there were like two ways to deal with the errors that either you fight on the first exception so you don't care about the other you get the first one, you raise it deal with it but then you lose track of all the other tasks that might fail as well otherwise you just like have this function and return a list of result maybe the result is an error so then you have like a list of errors but it works but you cannot use the exception tax where you can like do tie accept then catch a specific kind of error do this code now we have a list, we can like iterate the list do is and stands, my error is this kind of error but it's not as empty just like the tie accept syntax so exception group are a way to help with that so the way it works now you can accept with a star after the accept so in that case I have like a a task group that can trade many tasks and I'm going to talk about that later task group is a new Python 3.11 features what it does pretty much is like allowing me to run many tasks in parallel and when I get out of the context it's going to wait for all the tasks to complete however if the task from raising exception it's going to raise all the exception as a single group so here I have the accept star which means like if you throw, if you raise an exception group I want to catch the values of this type so even though I will have like 3 errors I have a value error divided by 0 and the index key error so I can tell my Python code that out of all these exceptions are being raised I want to have the value error I want to endow the value error in there the nice thing is that I could have like 2 of them I could have value error as well here and that way my exception group will have both exceptions so if I run this code we can see how it looks so I have catch the value error so here we see my code so my code I catch the value error, I print it and then I print like catch the value error and then I list all the exception that was part of it somehow I only have 1 so I'm not sure what happened oh I return demo god there we go so now I should have 2 of them so now I catch my exception group of type value error exception but I have 3 of them so there's still the other one the key error that I didn't catch so I'm going to go to my accept and once I go to all of them then it's like the default Python exception behavior so if I don't endow an exception it's going to keep going in my stack frame and I don't have any endlers so I just end up in the default Asyncio endler which is going to tell me you have one exception group it's still an exception group but it has only one exception even though initially it had 3 of them since I endowed 2 of them there's only one left so that's pretty neat for that like before I would have to do Asyncio gather and then I would have a list of the error back from it I'm just dealing with a list of the situation not as nice as doing the try accept and I could even do the accept the key error catch key error and now I won't have an endowed exception so yeah that's pretty neat in my opinion especially if you deal with code any pattern where you do many things in parallel and some of them might fail, some of them might not so I'm thinking about even a unit if we go back to this one so going back to our previous example of this test honor so I want to run all my tests and I don't want to stop at the first failure the first exception I see, I don't want to crash everything so I want to just collect all this exception and then I want to create a new exception group paste it, whatever call my test honor I can deal with the exception itself so taking the same code as I showed before to run the test now I have this small so I try to run my test if there's an exception I just add it to my list and at the end of my run all the test function I'm just going to raise it's missing if exception but if there's any exception I want to raise an exception group and it's very simple, just raise a group you have a classic exception you put a message first and then you can put a list of exception it's going to be included in this group so around my run test function accept store and then put some type on it so yeah, so this code works if I write that you see here the same code as before they will fail at the first test failing now I can select all my failed all my failed tests I have three of them they run at false, they run none and then they're empty list so yeah so that was pretty much it for the exception for error and language as a software engineer dealing with errors day to day sadly, sometimes we can't avoid the thing failing but moving forward the next change I want to talk about is about asyncio as I showed before this new test group it's pretty much the same as doing create tasks repeatedly and at the end of the day just do a gather asyncio that gather whatever it does you give it a list of tasks and then it will return either on the first phase or with the task complete so the task group is nice because it's like the context as I showed before I'm sure with because it's a context like whatever I do I can return in the middle a bit and it's still gonna wait for the task to complete so pretty neat in my opinion I think I would time out so now you can start the context give it a time out and then you can await tasks inside of it and when the time out it it's gonna cancel whatever tasks it's still running it's gonna raise a time out exception so there's way to do it before but there will be much more lines of code asyncio time out oops there's also asyncio barrier so barrier is a new synchronization primitive actually it's pretty much the exact context of a semaphore so semaphore is a more complexe mutex a barrier is pretty much give it a number of time you need to wait and then you can have a bunch of tasks that's gonna wait for it and it's gonna block until there's like n number of tasks that wait for it so in this example I create a barrier report 3 items I start 2 tasks in background that's gonna wait for it and these tasks are gonna block cause there's only like 2 weight being called then I sleep for 10 seconds and then after the 3rd weight I have my own main tasks that wait for it and it's gonna unlock the barrier so all the tasks are gonna keep coming up so it's pretty useful if you have some initialization of a team that has to wait for everyone to be initialized before keep moving or thing of the like however typing changes on all my types so like I use extensively my file to make sure it comes in Python since like the 4 last release so Python 3.0 doesn't let us down on that first of all there are the variadic generics so they are very useful to put the generic on the shape of the type you want so when we say shape it's a bit like a tupper like a tupper of int it's not the same as tupper of int like both are kind of the same dimension and the same type of each dimension for people using non-piles non-piles can have the array of many dimensions so like the number of dimensions and the type of these dimensions are kind of the shape so with this new feature people like library developers would be able to to make a function that take only like two array of the same shape so I won't be able to add at least my file will stream at me if I try to add an array of int with an array of string or an array of int-int with an array of int-int-int these are not the same shape I can't multiply them, I can't add them so it will allow to do the generic function to do that it's really useful for callable so like the callable you can give the first part of the callable the args that you can give to it however there's no way to like I want to give it a generic tupper argument and it's a bit difficult to explain with my word but I'm going to show you an example anyway however I tested today my file is still very unstable my test actually made my file crash and the new star is not working so I'm going to show a link like that so I have like this first example is from the Python documentation probably from the TEP it's a standard module in the process where you can create a process with the target that is a function and then you can pass like the argument that's going to be passed in the project so right now my type is no way to tell how my argument can be the same as the args that the callable gives without doing the events classes and that however now you can do first of all a type bar propose it's kind of like a type bar and then I can say like so my callable is going to get one of these many type bar and my args is going to be the same as well so it's going to take a top level of this new type bar so it allows me to have a signature of this process if I have this function take a string if I try to create a process for this function and I give it a string it's going to work but if I try to do the opposite string while I state the int please don't do that so that's pretty useful but unfortunately if I try to run that I might buy the latest release and my country will run I get an internal error on my face and nope Israël Il y a un sens statique commencable il y a environ 3-4 minutes sur le micro est-ce qu'il y a une batterie qui pourrait être faible dessous on va faire une connexion c'était super à claire quand t'as commencé et c'est à commencer à faire un peu de statique vous l'avez pas tellement entendu on a reçu le commentaire sur youtube donc c'est pas juste moi là je t'entends plus maintenant c'est ce que ça marche ah c'est très bon attendons juste un petit peu plus pour vérifier qu'il y a pas de statique à l'autre c'est ce que ça marche ah magnifique merci beaucoup en fait c'est plaisir oui en fait c'est ça c'est la nouvelle feature et quand je dis le syntaxe c'est que vous pouvez utiliser l'impact vous pouvez utiliser l'impact metotype pour expliquer que je veux faire un star mais avec le syntaxe vous devez pouvoir le faire c'est ce que je veux faire avec les args je veux l'impact vous devez pouvoir le faire pour ce type de table d'ailleurs je n'ai pas eu de support pour le type de table mais pas le syntaxe de star pour que ce soit possible de travailler dans le futur un autre exemple je pense que c'est plus bon donc j'ai un cas de use j'ai un arrêt qui est générique un type de table et puis j'ai une fonction qui multiplie deux arrêts de la même forme donc ils sont tous les mêmes types avec la même forme et ils retournent aussi en arrêt de la même forme le bon chose avec ça c'est que j'ai une seule fonction qui peut faire le magique pour tous les items de mon arrêt donc si j'ai cette première arrêt et je peux utiliser les littéraux je peux dire que mon arrêt va être 100 langues mon deuxième arrêt va être 4200 langues donc je ne peux pas multiplier parce qu'ils ne sont pas les mêmes types j'ai cette troisième arrêt c'est comme le type d'autopiles que vous ne pouvez pas faire avant en Python sans faire un type pour chaque possible compte de dimension maintenant je peux dire que mon arrêt est de 2 dimensions la première est 100 langues la deuxième est 42 langues je ne peux pas replier quelque chose si ils ont exactement le même type donc je peux replier 142 je peux replier 142 je vais avoir un erreur pour chaque arrêt et interestingly ça fonctionne si je vous le souviens oui, donc ça va me cacher si je regarde comme le erreur la ligne 21-22 la première fonctionne la deuxième devrait travailler c'est comme ça mais la deuxième depuis qu'on a le même type ce n'est pas fonctionnel donc ma paille fonctionne parfois ce n'est pas fonctionnel c'est encore très stable un autre chose c'est qu'à ce point on peut faire ça avant avec un peu d'extras donc maintenant vous pouvez marquer un item individuel type-dick comme un nouveau type donc c'est un meilleur moyen de mélanger votre dictionnaire avec ce qu'il faut un autre caveat c'est que ma paille ne cares pas d'autre chose donc si vous essayez d'accesser une valeur optionnelle ça va être ok même si vous n'avez pas de garantie donc un exemple c'est ici, donc c'est bien ce que vous allez faire avant un Python 3.11 si vous voulez avoir un mix de optionnel une paille de type-dick vous avez la première pour avoir votre requiert type-dick donc j'ai ma paille basée que j'ai utilisé le default type-dick toutes les pailles sont requiertes puis j'ai créé cette nouvelle classe qui est ingénieuse de l'autre mais ça dit que mes nouveaux attributs vont être non totals optionnels et c'est bien je peux créer un film avec un titre parce que le titre est requiert mais je peux créer un film avec seulement un an mais avec le nouveau syntaxe je peux avoir une seule classe j'ai une classe type-dick et pour mon requiert je peux juste les marquer donc ça fonctionne comme avant si j'ai un titre, ça fonctionne si j'ai une année, tu peux me dire tu dois avoir un titre, c'est requiert mais comme je l'ai dit maintenant c'est intéressant parce que dans ma VMID tu peux voir que j'ai un type-arrêt tu peux me dire que tu n'as pas accès mais c'est en utilisant Pi pas ma Pi si j'ai mon Pi il va me donner l'arrêt pour la première donc le titre m'a dit mais il ne va pas me donner l'arrêt car il n'y a pas de code et le plus petit improvement dans la typing, il y a un type-self donc pour dans le passé tu aurais besoin si je veux avoir une fonction de copie je dois savoir le type de ma classe donc je peux détenir ma fonction je vais avoir une copie pour un parent peut-être que j'ai un enfant pour un copie pour un enfant donc tu peux juste payer la définition car ça ne marche pas mais avec la nouvelle version tu peux utiliser le type-self pour un parent tu peux juste payer le self et il va être infert comme parent si j'ai un enfant maintenant je peux juste payer la définition de la fonction et ça marche pour la classe donc quand je retourne le self je vais retourner le type de la fonction encore un type improvement il n'y a pas de support pour un type littéral il a parlé de ça dans la présentation 5 mois auparavant ce que ça fait 3 mois donc ça vous permet d'avoir un type qui ne tient que le type littéral c'est pas le même que le type littéral le type littéral vous permet de dire que cette valeur est littérable c'est seulement 1 c'est seulement 2 mais vous pouvez dire que c'est un type littéral c'est le type littéral ça vous permet d'execuer la fonction d'execuer tout ce que vous passez c'est un variable parce que vous ne pouvez pas s'occuper d'execuer un code de safe donc j'ai maintenant cette fonction qui prend un string littéral la seule façon que vous pouvez prendre cette fonction si j'utilise un string qui est dans le code si je vais essayer de lire l'input de l'usage et prendre ma fonction avec ça ce que j'ai fait c'est que le type littéral peut s'occuper c'est le type littéral je ne l'ai pas testé si j'occupe ce code c'est working car je ne passe pas un string littéral donc le type de define mais ils ne sont pas check donc c'est un Python qui traite le support de Python 3.11 donc j'ai maintenant un variable qui n'est pas working comme je l'ai dit le type littéral juste cache et le string littéral ne cache pas mais il ne vous donne pas l'erreur le type littéral est inspecté donc la implementation de la currentite est juste la laissée et comme il n'y a pas de nouvelles features c'est une note il y a un peu de future annotations la future annotation est une évaluation laissée de type annotations donc maintenant quand je define un class et je veux retourner mon type il faut le mettre en string car ce type, si je regarde le class B si j'essaie de retourner la première chose, le class A il ne marche pas sur Python 3.10 il va me dire que A n'existe pas parce que je suis toujours dans la définition A donc avec la future evaluation ça va permettre le class A de travailler parce que le type annotations sera évalué à la fin de leur file plus tard quand A est définie mais c'est supposed de être évalué en Python 3.10 puis il a postponné au 3.11 pour qu'il y ait un peu d'issues qui doivent être déclarées ce n'est pas aussi simple il peut changer un code donc peut-être que l'on ne va pas juste un peu de questions j'ai assez de temps j'ai eu de l'argent maintenant on va appréhension donc maintenant on peut faire un sync pour insider pour faire ça le 2ml est un standard d'installer un nouveau module, c'est parce que le pyproject est à 2 ml, on peut les lire dans le Python. Un petit truc que j'ai utilisé dans le passé, c'est que le format de chromosome et le temps de date supportent la plupart des formats de chromosome 86 ou de 1. Nous pensions qu'on allait juste soutenir le format généré de Python. Si vous finissiez avec le Z, c'était un casque qui n'était qu'un plus de 0,00.00. La zone de temps était comme un petit truc. C'était un bon implementement. C'est comme un minimum, mais où chaque valeur peut être utilisé comme un maximum. Il y avait un moyen facile de le faire, mais maintenant, c'est un peu de l'épisode, c'est bien. L'un que j'ai utilisé, c'est ce qu'il s'appelle « catastrophe backtracking » Il y a 4 caractéristiques qui vont prendre beaucoup d'heures pour consommer l'input. Donc maintenant, il y a un nouveau processif contre le feu. Il peut avoir beaucoup de « catastrophe backtracking » Je vais avoir un lien qui n'explique pas. C'est une bonne feature. Par type, il y a un certain nombre d'asserts. Vous pouvez faire un « if » et un « if else » et vous pouvez essayer d'asserts. Vous n'aurez jamais atteint un « if else » mais il y a un moyen de le faire. Il y a aussi un type d'assert que vous pouvez utiliser. Un type d'assert, c'est un type de « x » qui veut asserir un type de « int ». Maintenant, vous pouvez faire un type d'assert qui ne fait pas de « x » mais quand vous voyez que le type est faible si vous avez un type, c'est pas le cas. C'est très bon que maintenant vous pouvez asserir un type et vous pouvez facilement utiliser le type d'assert. Enfin, vous pouvez asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert qui veut asserir un type d'assert que vous app heute且 vous pouvez aller où Carester et Euhub vous pouvez PW il y a un tunnel d' Survey et il a peut-être une introduction arranged à un shrink happen Je ne sais pas ce qu'ils ont passé mais la statique est revenue. Ok, c'est bon ça? Ok, je vais juste utiliser mon code de performance. Ok, merci. As I was saying, Python 3.11 is 35% faster than Python 3.10 in average in the benchmark of C Python. You don't have to change anything. These are all improvements called Python. There's no such thing. It's much faster if you use this specific pattern. Whatever code you use is going to be faster. The startup time is 10-15% faster. The startup is not even code that you write. Whatever tool you have, it's going to be faster. Just a quick note, during the emulation to Python 3.11, we did it on our code base, which we have quite a lot of Python. The little friction that we hit is the dependencies. Like any Python version, if you are still using all dependencies, you reach a point with all these dependencies. They don't build the real package for your new version. Let's say you use your PCIO. If you use all your PCIO version, you're going to end up compiling all the code above libraries and things like that. Which is very annoying, first of all. You're going to have failure, compiler is going to fail. Just use the wheel package. It's going to save you a lot of time and a lot of time. The first thing is updating your dependencies is going to make things much easier because then you're going to have access to all these wheel packages. Also, for the data class errors, the only error that I saw while migrating, and that I found my dependencies, now that that class is going to check, when you have a default, I know if you try to do a data class with a default empty dictionary, it's going to give you an error. It's going to tell you that you can default to admissible values when you print later on. So you have to use the default factory. But now it does that for any type, not just dictionary or list or anything like that. Anywhere where you have a default, they call my custom class that used to work, now it's going to raise you an error. And some of your dependencies might have this pattern that raise you an error. So you have to fault dependencies, or you just have to update them. Other than that, the migration was pretty smooth. We have a lot of that, and only one of them, that data class issue that we fixed. And yeah, I'm pretty much done. I've done this content. So the next Python release is that we're going to have the same unpacking tags for the codewargs. So now we will be able to use a type dict to type your codewargs, which is pretty neat. Like before, it will be only able to type the dict. So all my keys are going to be string, or all my keys are going to be anything. Which is not that useful. Now you're going to be able, my codewargs has a name and a year, and they're going to be type string and int. Also, it's going to be the override decorator, so you can explicitly say this method is overriding a method from the parent. So if you do a typo, or if you forgot to put a method in your parent, it's going to give you an error. You're going to tell you, that's not in your parent. So yeah, that's it. Thank you. Any question for this parent? Yup. No particular leaves. Just a few CPI breakage on the end of that, but for the most popular dependencies, they follow most of the time, like the Python release, or PyTorch is working on 3.11, should be working Django as well. If you have smaller dependencies, like the Data Class is the one that will be working on 5.11, that's all. And on the other side, C'est comme je l'ai dit, la classe de données est celle qui m'a frappé le plus. Les gens utilisent la classe de défaut, ce n'est pas défaut. C'est used pour le travail, ça ne marche plus. Mais ce n'est pas beaucoup de change de comportement. Je pense qu'il y a des décrétés, des nouvelles choses, mais il n'y a pas de change. Merci. Oui? Si tu l'entends, c'est bien. Si tu l'entends, c'est bien. Bonne question. Je vous répète de la ligne. Si j'ai mis le PDB module sur ma code, je vais avoir la ligne. Je ne l'ai pas d'explication. Je ne l'ai pas d'explication. J'ai pensé que la ligne de PDB est assez compliquée. La ligne de PDB est partie du module de la ligne. C'est comme la carte. La ligne de PDB a un speed de 45% de la version 6.11. Tu vois ça? Toutes les fibres? Ou tu utilises les fibres? La question est, l'augmentation de speed n'est qu'une pièce de pièce? Ou une pièce de pièce de pièce? Oui, tout. Si tu regardes le change log de pièce, c'est une variété de speed. Je regarde ça. La pièce est la pièce de pièce. La ligne de PDB est la pièce de pièce. Il peut être pièce, ou peut-être de pièce personnellement. Il peut être plus rapide. La pièce de pièce est compliquée, la compétition de pièce est plus rapide. La crée de management est plus rapide. Juste, any Python culture will be faster, whether it's like the built-ins module or the property. Thank you so much, everyone. So anyway, if you guys have any other questions, Israël, we'll be here. So do we need a break for a soda or take another beer or I don't know? Or we can continue? Oh, OK. We continue. So here you guys want to... OK. On va marquer tout de suite avec Romain d'abord. Est-ce que tu nous entends toujours, Yannick? Ça roule super bien sur le stream. Le son est top notch depuis qu'on a changé la configuration de micro. Merci. OK, cool. OK. Mais c'est ça. C'est comme tu dis, il y a toujours la vie, là, si vous avez so, vous pouvez toujours continuer. Aussi, j'ai oublié, on a notre photographe avec si vous pouvez faire des beaux souris, là, comme ça on va mettre sur notre site pour ne pas mourir un peu. Bon, je vous laisse avec Romain. Merci. On va attendre 5 minutes. Tout le monde va se faire installer. C'est bon? Oui, c'est bon. Très bien. C'est ça, c'est ce que tu voulais? Oui. Et là, si tu penses que j'imagine que si tu fais ça comme ça... C'est petit. OK. Ah, c'est vrai. OK. Ah, oui. Ça suffit à rigoler ça? Oui, c'est bon. OK. Super. Bonsoir à tous, merci d'être venu. Je m'appelle Romain et je vais faire ma première présentation de Python Montréal et puis ma première présentation tout court en public. Ce soir, je vais vous parler du double fork et du lancement de processus de longue durée en Python, plus particulièrement en web avec Django. Donc pour vous présenter, je suis développeur logiciel chez FVNR. Ça fait un an que je travaille chez eux. Avant ça, j'étais à Bruxelles. Je suis ingénieur de formation en France, mais ici, je n'ai pas le statut d'ingénieur, donc je n'ai pas le droit de le dire. J'aime le surf et les sports de montagne, donc c'est tout naturellement que j'ai choisi Montréal pour venir habiter. Et puis voilà. Donc je vais vous d'abord vous présenter les problématiques. Qu'est-ce qui amène à penser qu'on a besoin d'un processus de longue durée ? On va avoir ensuite les tâches à synchrone, un petit rappel en unique sur les threads, process, process group et sécession. Ensuite, on verra le principe du double fork et on verra les exemples en théorie et en pratique. Donc si on prend l'exemple d'un site internet, si vous avez un site relativement classique, si de vitrine, vous n'avez pas besoin d'énormément de ressources, mais si vous ajoutez des fonctionnalités un peu plus techniques, donc par exemple, faire des exports, envoyer des emails de registration, faire de la synchronisation de données ou encore nettoyer votre database de temps en temps, vous allez avoir besoin de processus. La limite conventionnelle, c'est de 30 secondes en web pour avoir des réponses, mais en termes de user expérience, on aimerait bien que le temps de réponse soit assez court. Quand je clique sur un bouton d'export, je ne veux pas attendre 30 secondes que le bouton tourne et qu'on charge. J'aimerais avoir une réponse assez rapide. Donc c'est pour ces raisons qu'on a besoin de process qui tournent si possible de seuls en arrière-plan, qui font leur job, qui partagent les ressources, puisque si un utilisateur fait un export qui demande beaucoup de ressources, je veux que les autres utilisateurs puissent continuer à les visiter les pages, que le même utilisateur, je ne sais pas, on veut pouvoir arrêter et redémarrer au besoin ce processus, et on veut qu'il accéde aux ressources comme le code, mais aussi la database, les médias, les images de notre site. Par exemple, si je suis un utilisateur et que je demande un export à mon site, on peut faire une réponse directement lui disant OK, l'export est en cours, et derrière, on lance une tâche à Synchron qui va faire l'export et qui lui enverra le résultat quand l'export sera prêt. Pour ça, il existe déjà des solutions comme Celeri en Python qui fonctionnent sur des tâches soit ponctuelles, soit des tâches qui sont prédéfinies. Donc, par exemple, lancer tous les jours à minuit une tâche particulière. Le souci, c'est que qu'est-ce qu'on peut faire pour des tâches qui sont plutôt en continu ? Donc, typiquement, faire de la mise à jour de données en continu par rapport à un système tiers. Donc, si je demande de synchroniser sur mon site les données, je n'ai pas demandé à l'utilisateur d'appuyer toutes les cinq minutes de faire un bouton pour synchroniser les données. Ça n'a pas trop eu de bler et je ne vais pas non plus payer quelqu'un pour le faire. Donc, les problèmes qu'on a ici, c'est qu'on a une action continue qui va accaparer les ressources. Parce que si on lance une tâche Celeri qui passe son temps à faire les demandes de données, elle va empêcher les autres processus Celeri et les autres tâches de bien s'exécuter. Ce qui va augmenter, du coup, le prix aussi de nos serveurs puisqu'on va devoir plus de workers ou d'agents Celeri. Ce sont les petits serveurs de Celeri qui exécutent les tâches. Au plus on a de tâches, au plus on va en avoir besoin et donc, au plus, ça va être difficile de ce qu'il y ait. Et aussi, il y a une notion de priorité. C'est-à-dire que si j'ai une tâche qui tourne en continu, comment je sais qu'il y a la priorité sur une nouvelle tâche qui va assoncer ? Est-ce que je dois finir la tâche qui est avant mais qui est en continue donc qui va jamais lâcher la priorité ? Ou est-ce que c'est à chaque fois la nouvelle tâche qui va prendre la priorité ? Donc là, Celeri là-dessus est limité. On part son nom d'agent par la gestion de priorité de ressources et donc pas adapté aux tâches continues. Et c'est là que rentre en jeu le double fork ou les démons en piston qui va en fait fonctionner en parallèle du code. Ils vont s'exécuter de leur côté avec leur ressources. Alors, avant de rentrer dans les détails de comment on fait le double fork, je voulais vous faire un petit rappel en Unix. C'est autant rappel pour vous que pour moi puisque ce n'est pas mon domaine de prédilection. Donc j'ai fait mes recherches pour mieux comprendre. En Unix, on utilise des sessions. On paye plusieurs sessions, mais il y en aura toujours une qui sera prioritaire en avant. Ces sessions gèrent des groupes de process qui sont composés de process et ces process peuvent être composés de thread. Les sessions sont contrées là avec un terminal ou du tty, tty, je ne sais pas comment on dit. Et tous ces objets sont identifiés par leurs ID. Le groupe de process qui est en gestion de la session est appelé le groupe leader et chaque groupe de process a un process qui est prioritaire, qui est premier et qui est aussi le leader. Ce qui fait qu'on a plusieurs leaders en process, mais il n'y a qu'un seul process qui va lider la session, c'est le process leader du groupe leader. Et seul, le session leader, donc le premier process du premier groupe peut contrôler le terminal de la session. Le principe du double fork, c'est en fait de créer un démon. C'est un process qui va rouler en arrière-plan. Et ce qui fait la particularité de ce process, c'est que son parent, donc le process non-tilérite, est terminé et ce démon n'a pas de terminal. Il n'a pas le droit de contrôler un terminal par mesure de sécurité. Comment on fait pour créer un démon, donc on utilise le process de démonisation, on utilise le double fork, qui nécessite en plus, ce qui n'est pas indiqué dans ce nom-là, de découpler la session, c'est-à-dire qu'il faut changer le process de session pour être sûr qu'il n'appartient pas à la session qui gère la session principale. Donc l'exemple de code qui est disponible sur Internet, c'est vraiment la version minimale du process, consiste en trois étapes. Donc la première, c'est de faire un premier fork pour s'assurer que votre process ne sera pas le leader de sa session. Ensuite, ce qu'on voit, les trois lignes, c'est pour découpler, donc créer une nouvelle session pour s'assurer que le process ne sera pas dans la session leader. Le Unmask, c'est juste pour permettre votre process de pouvoir accéder aux données, faire de l'écriture et de la lecture. Et on refait un fork pour s'assurer que le process qu'on a créé ne soit pas non plus le leader de la session qu'on vient de créer. Comme ça, on est sûr qu'il ne prendra jamais le contrôle de n'importe quelle session. En exemple, avec des chiffres, ici, par exemple, on a notre session actuelle, la session 46, avec le groupe de process 84 et le process 84, qui est leader de son groupe. Après le premier fork, on va voir notre process 85, donc c'est la ligne 2. On va ensuite découpler ce qui va permettre de plus être dans la session qui dirige l'OS. Et, une dernière étape, on fait un dernier fork, comme ça, on est sûr et certain que si jamais, pour X raison, il se passe des choses dont on n'a pas conscience, le process ne pourra jamais récupérer la session puisqu'il n'est plus le leader de la session. En pratique, c'est le démon que nous, on a mis en place dans dot code. On voit qu'il y a bien la fonction ici que je vous ai montré juste avant. Et nous, on a rajouté quelques fonctions pour permettre de s'assurer que le démon est unique. Donc, on a le start et le stop. En fait, ce qu'on fait, c'est que, quand on lance le process, on vient écrire son ID dans un fichier. Et quand on vient le démarrer, on regarde si l'ID existe. Si il existe, c'est qu'on a déjà un démon qui tourne et donc on interdit la création. On a un message d'erreur. Et pareil pour l'arrêt, quand on veut l'arrêter, si il n'existe pas, on met un message d'erreur comme quoi le process n'existe pas. Et comme ça, on s'assure qu'on n'a qu'un seul process qui tourne pour la tâche qu'on a envie d'exécuter. En exemple ici, donc, l'exemple qu'on a ici, c'est une classe abstraite. C'est-à-dire qu'il faut l'implémenter pour pouvoir derrière faire les différentes citations qu'on veut. Et donc cette classe-là, c'est une implémentation que nous, on utilise actuellement qui s'appelle Sinker, puisque l'objectif de ce démon-là, c'est de tourner en continu et de synchroniser les données avec un système tierce. Donc on a notre code qui roule, on a notre site qui permet de faire des exports, des envois d'email, etc. Et en parallèle, on a ce démon qui tourne tout seul de son côté et qui va sans arrêt questionner un site tierce pour récupérer des données et mettre en place nos données. On a simplement la fonction run ici, à préciser, parce que si vous voyez ici tout en bas, il faut l'overwrite pour créer son démon. Et en dessous, vous mettez les fonctions qui correspondent à votre logique métier pour faire fonctionner votre démon. J'aurais voulu bien faire un exemple, mais comme il y a des données clients, je vais vous faire un écran. Donc on est sous Django, donc on doit utiliser les fonctions Django pour lancer notre démon. Donc là, on est sur le serveur du projet. On fait un simple start en précisant la fonction Django qui va lancer le démon. On a ici un fichier de log dans lequel on log ce qui se passe avec le démon pour pouvoir s'assurer que tout fonctionne bien. Donc on voit que ça tourne tout seul. Et après, pour l'arrêter, il suffit de faire un simple stop que l'on a vu juste avant. Actuellement, nous, on utilise deux démons, un qui permet de récupérer des données en continuant et en temps réel. On a un autre qui fait du calcul de cache. C'est-à-dire qu'il va pour les pages les plus visitées et les requêtes les plus faites, il va alimenter une base de données qui permet en fait d'aller charger les pages plus vite. Et pour le vent, on gère tout ça en ligne de commande sur le serveur. Les pistes d'amélioration et ce qu'il y a à prendre en compte pour le gérer les démons, c'est premièrement, on peut proposer une gestion directement en ligne, puisque comme c'est du piton, on peut tout à fait créer une page web pour les techniciens qui pourraient seulement eux pour y avoir accès pour gérer le démarrage et l'arrêt et la gestion du démon. Et comme c'est un process qui tourne en continu, on veut à tout prix être au courant des erreurs et des blocages qu'il peut y avoir sur le bon déroulement du process. Nous, par exemple, ce qu'on a en place actuellement, c'est un système d'email. On a de la détection d'erreurs qui nous envoient des emails pour dire, attention, il y a une erreur où, attention, là, il y a quelque chose de ce qui ne se passe pas comme ça de vrai. Mais il y a encore plusieurs pistes d'amélioration. Et vous pouvez bien évidemment créer la suite de ce que vous forcez pouvoir ajouter. Pour les sources, si jamais vous êtes intéressés, il y a beaucoup d'exemples. Et notamment, le premier que je vous ai montré qui est vraiment la base du démon qui est très facilement réutilisable pour les besoins de vos applications. Merci. Merci. On applaudit Romain. C'est sa première présentation tout le monde. Est-ce qu'on a des questions pour Romain? Je regarde aussi sous. Online, j'ai complètement oublié qu'on a deux trucs. Yannick, tu gères, est-ce que tu vois des questions en ligne? Je ne vois pas de questions pour l'instant, mais je garde un coup d'oeil sur tous les endroits où on reçoit des questions, donc les commentaires sur YouTube et sur Slack, et puis je vais les relayer de vive voie si on en a. Merci. Moi, j'ai une question. Est-ce que ça vaut la peine d'écrire tout ça? J'ai l'impression que j'ai pas reçu toutes vos affaires, mais est-ce que ça donne le résultat vraiment qui est vraiment votre problème? Je sais pas si que oui. Si on utilisait ces lérits pour faire nos tâches, le problème c'est que comme on fait de la synchronisation en temps réel, on ne sait jamais si la tâche est terminée pour lancer une suivante. On ne sait jamais si c'est une erreur. Alors qu'avec le démon, on a vraiment tout qui se fait d'une seule traite et on arrive à catch le moindre souci. Donc on n'a pas de blocage et pour l'allocation des ressources, c'est beaucoup plus simple, parce que le démon gère tout de son côté. Tout à fait. Nous, sur notre projet, on a deux serveurs. On a le serveur de synchronisation qui fait rouler les démons et les tâches. Et le serveur de classique qui se contente d'afficher les pages, de renvoyer les données au frontaine. Non, en fait, on a deux serveurs différents et le serveur de sync n'est pas accessible par le frontaine. C'est une bonne question. Je pense qu'on pourrait faire les deux sur le même serveur. On n'a pas encore fait vraiment d'études si on en avait un grand gain de temps. Si on avait un serveur assez puissant, on pourrait faire tourner les deux sans problème. Le frontaine l'échange avec le frontaine et les tâches chénéries et le démon. Non, pour le grand, nous on le remet manuellement. Je m'excuse de la interruption. Pour le bénéfice des gens qui suivent sur YouTube, pourrais-tu répéter les questions? La question c'est qu'est-ce qu'il se passe si le démon crache, est-ce qu'il se relance tout seul? Pour le moment, non. Le système que j'ai mis en place c'est que s'il y a un fichier qui existe avec l'ID, ça veut dire que le sync est censé tourner. Ce que je fais, c'est que je check s'il y a eu des tâches dans les 30 dernières minutes. Si on n'a pas eu, j'envoie un mail qui dit le sync est censé tourner, mais ça fait 30 minutes qu'il ne se passe rien. Il faudrait quand même aller voir ce qu'il se passe. Donc pour le moment, ça envoie un mail. Moi je vais manuellement voir ce qu'il se passe et si vraiment il y a un problème, je restart. Je l'éteins et je le relance. A propos de des achatements réels, vous avez des cistrilles qu'on peut trouver une résolution avec des containers qui reviennent du système d'exploitation pour s'il y a tout le fort qu'on peut rouler toutes les solutions des containers distinctes ou des coups et on peut être un container qui est fonctionnel. Et c'est la même possibilité on peut c'est cela que vous pouvez rajouter un problème parce que vous avez il n'y a pas de résolution pour voir les données fécurées. Pour avoir une mise à jour continue ? Pour avoir une mise à jour continue ? Pour avoir une mise à jour continue ? Oui, c'est ça. Et la solution serait ? Une des solutions. C'est possible, c'est pas une piste que pour la question j'ai un peu du mal si j'ai bien compris ce serait d'utiliser des containers dans plusieurs containers lancer la tâche et récupérer celles du container qui réussit ? J'ai assez peu de connaissance dans les systèmes Minix pour voir si c'est possible mais je me demande si ça prendrait pas trop de ressources parce que ça serait assez exponentiel comme solution c'est-à-dire qu'on devrait créer plusieurs containers et qu'il y en aurait beaucoup qui servirait entre guillemarien donc c'est peut-être dangereux mais j'ai pas la réponse. C'est-à-dire que si c'était sur l'entrée compétitive c'est pas con le fait d'avoir des terres le fait qu'elle demande un temps de tâche dans un ordre de priorité qu'elle fera du moment possible ou qu'elle fera que l'on a vu dès que c'est fini et qu'on reprend et d'abandonner parce que là c'est pas la même manière d'y aller. Parce que c'est de trouver une solution à la combler et on va à l'aide de l'entrée. C'est-à-dire que si ça n'archerait pas que ça n'allait pas être important mais soit bien avec les avancées des lignes, ça n'allait pas être un peu différent. D'accord, merci. Si nous de toute façon tu restes avec nous Ah oui? Ah oui, il y a beaucoup de monde. C'est bon. Je vais juste conclure ça. Yannick, tu es toujours là? J'y suis, oui. On a toujours un verre, non? On a toujours un verre, non? On a toujours un verre, non? On a toujours un verre, non? Où est-ce que tu es? On a toujours un verre, non? On a toujours un verre, non? Oui c'est ça. C'est terminé. D'accord. Merci tout le monde d'avoir online. Je ne sais pas que Yannick a pas connu C'était super cool. Est-ce que tu veux venir Yannick juste pour voir si j'ai pas oublié quelque chose, mais je pense pas que... Ah, on a perdu Yannick. Ben non, je suis encore là. Non, ok, non, ok. Ah oui, j'avoue que... J'avoue que... Est-ce qu'on peut... Oui, mettre Yannick online pour que les gens le voient parce qu'il y a assez... C'est bon? Non, non, on met... Ah, ok, c'est cool. Yannick, crazy. Ah oui. Bonne soirée tout le monde. Je suis vraiment content qu'on se rencontre en personne. Encore une fois, même si moi je suis pas en personne. C'est toujours bon. Je vous invite. Je vous invite. Attends, Yannick. Et puis, je vous invite... Vous aussi. Et puis les gens qui sont en ligne, y'en a pas beaucoup en ligne parce qu'on a eu un petit changement d'ur. On va quand même démarquer le 5 à 7 virtuel. Depuis quand vous parlez, ça a coupé. Ah. Non, tu veux plus rien dire? Ah, on est repartis là. Est-ce que vous vous attendez? Ah, il y a de l'écho aussi dégueulasse. Ce que je voulais dire. Bienvenue à Montréal Piton en personne. Et puis moi, je prends une bière en passant à vous. Et puis très en une en passant au Piton. Peut-être à moi. C'est pas grave. C'est bon. Nous aussi, on va aller prendre des bières ici. Puis on a la pizza qui s'en vient. On te laisse. Bonne soirée tout le monde. Donc, on vient de perdre nos amis qui sont en 5 à 7 physiques. Et je vois qu'on n'a pas énormément de personnes qui sont sur le livestream. On s'excuse du changement du URL. Je sais que ça peut induire la confusion. Mais je vais vous paster tout de suite un lien. Si je suis capable de copier ça. Il faut que je démasque un petit instant. Je vais paster dans les commentaires YouTube. Un lien vers où on va avoir le 5 à 7 virtuel. Et je re-registre ça. Un petit instant. J'affiche commentaire. Et zoop. Donc, je vous rejoins à 7 URL dans un instant pour le 5 à 7 virtuel. Arrivée avec votre rafraîchissement favori. Et ils ne nous auront pas autant d'amusement que nos amis sur place. Mais on s'amuse quand même. A tout de suite.