WEBVTT 00:00.000 --> 00:09.040 Cool. Hello, I am Safond Rahman. I am actually 00:09.040 --> 00:14.280 have come from Bangladesh. My topic is actually very interesting one and it is not very 00:14.280 --> 00:19.120 like the thing that people try to do and everything. So, it is about like monkey 00:19.120 --> 00:24.560 patching. So, monkey patching is something that you change the code at the runtime. It is 00:24.560 --> 00:31.560 very bad practice, but at least sometimes you need to do that. So, use that in your own 00:31.560 --> 00:40.840 risk. So, the thing is that do not try this at home. Sorry, do not try this at production. 00:40.840 --> 00:49.840 You can try this at home, but you should not try this at production. So, have you ever used 00:49.840 --> 00:56.840 that in your code rather than test? Anyone who is that? Oh, okay, a lot of people who 00:56.840 --> 01:09.840 are with that, okay. Have you pushed monkey patch to do the reproduction? Okay, not 01:09.840 --> 01:16.840 wrong, not Raj. Okay, so, okay, sure. 01:16.840 --> 01:23.840 So, the thing is that, my topic is actually how we can actually use the monkey patching, 01:23.840 --> 01:29.840 the function, this powerful functionality more beneficial for our debugging our code and everything. 01:29.840 --> 01:34.840 Okay, because maybe you should not push this code to the production, but you can use that 01:34.840 --> 01:41.840 this code in your local machine to actually test things and also like debug your packages 01:41.840 --> 01:47.840 the thing. So, while there are bug in a package that you are using is quite difficult to actually 01:47.840 --> 01:55.840 fix that or like debug that in locally and then you can actually get a fix, right. So, 01:55.840 --> 02:00.840 this is a short example as we will all know that how to actually do the monkey patch. 02:00.840 --> 02:09.840 So, in the class, in the class dog there is a method in a bug, but if you actually see 02:10.840 --> 02:17.840 is that after we actually, we are getting the animal object in there and we are actually 02:17.840 --> 02:23.840 making the bug, we are calling the bug function is actually, is actually showing the roof 02:23.840 --> 02:28.840 in the output, okay. But after we actually monkey patch the bug function in this new bug 02:28.840 --> 02:36.840 with this new bug is actually returning the meow, okay. So, this is how we can actually 02:36.840 --> 02:43.840 monkey patch a class directly in python code, okay. This one is actually important one 02:43.840 --> 02:52.840 because like you can make you can monkey patch a class very easily, but it is quite difficult, 02:52.840 --> 02:58.840 what not quite difficult is quite tricky to actually patch a instance or like a object in python, 02:59.840 --> 03:05.840 okay. So, like if you want to, if you need some parameter or anything from your 03:05.840 --> 03:13.840 base class in your function in your class method, what you need to do is that you need to 03:13.840 --> 03:19.840 use the method type, okay. So, if you need to use the method type in that case that as 03:19.840 --> 03:26.840 you see that I actually have patched the gate name function in here with this function 03:27.840 --> 03:32.840 and after we actually use the method type, we could actually, we could actually 03:32.840 --> 03:37.840 access the self-value from the, from the monkey patch function as well, okay. 03:37.840 --> 03:44.840 So, the output will be, the first output will be type, okay, because this is the type, 03:44.840 --> 03:51.840 but in the after monkey patching it will be my name is type, okay, because the monkey patch 03:51.840 --> 03:58.840 function is actually getting the value from the, from the after main class main object, 03:58.840 --> 04:04.840 okay. So, this is the main part, okay. So, how we can actually use the monkey patch to 04:04.840 --> 04:09.840 which we debug, okay, you know, look at me, okay, because maybe we should not push this 04:09.840 --> 04:14.840 code in the production, but we can actually use the monkey patch function to debug our third 04:15.840 --> 04:20.840 package, that we are actually using and maybe that third-party package has bug in there, 04:20.840 --> 04:26.840 okay. So, think about a like a third-party package, it is about like the kelp module, 04:26.840 --> 04:32.840 okay, it has a like, it has a function, this name is kelp, kelp, let's sum, okay. 04:32.840 --> 04:36.840 But it seems like the kelp or sum actually has a bug in there, because other than 04:36.840 --> 04:41.840 calculating the sum, it is actually abstracting that, okay. So, if you actually face this kind 04:41.840 --> 04:45.840 of issue, what would actually you do, okay, in this third-party package, either you can 04:45.840 --> 04:50.840 fork that, you can install that package, vendorize that, anything, but it is quite difficult 04:50.840 --> 04:56.840 to do that. So, in order to debug that, what you can actually do is that you can, you can 04:56.840 --> 05:02.840 import this function as the wrong kelp has a different name, and then you can actually 05:02.840 --> 05:08.840 write another function, okay, like a pairs kelp or sum. So, in the pairs kelp or sum, you 05:08.840 --> 05:12.840 can actually add a break point in there. So, you can understand that what's parameter you 05:12.840 --> 05:17.840 actually getting on in this function, and then you can return the wrong calculation sum 05:17.840 --> 05:22.840 method in there, okay. So, after that, we are actually monkey-watching in there, like we 05:22.840 --> 05:27.840 are term monkey-watching the kelp module, kelp module dot kelp sum, kelp for we actually 05:27.840 --> 05:36.840 monkey-watching the kelp sum in there with our pairs, pairs function in there. So, when 05:36.840 --> 05:40.840 when we are actually importing, this is the very important thing, you should always 05:40.840 --> 05:45.840 monkey-watch before you actually import the actual method, okay. So, if you actually 05:45.840 --> 05:50.840 patch after importing the method or function, you cannot actually monkey-watch that, 05:50.840 --> 05:56.840 write this way, okay. So, if you actually import the kelp module, kelp sum from the kelp 05:56.840 --> 06:01.840 module, and you actually call that function, but you will, you will see that you will 06:01.840 --> 06:05.840 actually get a PDB, okay, you will actually get a debug interface in there. So, in that 06:06.840 --> 06:11.840 debug interface, you can get all the variable and everything, and so that you can actually 06:11.840 --> 06:16.840 debug it more precisely that what is actually happening in there. 06:16.840 --> 06:22.840 This is the second example. So, actually debug that, okay, there the third 06:22.840 --> 06:28.840 party library has a bug. So, how can you fix that in your local machine? So, you can actually 06:29.840 --> 06:35.840 test that, this is the main course, okay. So, what you can do is that, you can, with 06:35.840 --> 06:40.840 the same way, you can just other than adding the debug, like a debugger, you can 06:40.840 --> 06:48.840 actually kind of fix the method in there, and you can actually paste, you can actually 06:48.840 --> 06:54.840 paste that, okay. So, after patching that, if you actually import that, import the function 06:54.840 --> 07:00.840 that module, you will actually get the actual result. So, at the first, I am actually 07:00.840 --> 07:07.840 getting the 70, because the function has a bug, but after we actually paste that and fix 07:07.840 --> 07:13.840 that, I can actually, I am actually getting 130, because this should be 130, okay. 07:13.840 --> 07:19.840 So, this is the interesting one, another one, interesting one is that, sometimes you need to 07:19.840 --> 07:24.840 know that while debugging that, from where this third party function is being called, 07:24.840 --> 07:28.840 okay. So, you have a like, thousands of sounds of flying in a scope, you have like 07:28.840 --> 07:33.840 a lot of packages, like 100 of packages, you need to know from which packages and from 07:33.840 --> 07:39.840 where this function is being called, okay. So, what you can do is that, you can actually 07:39.840 --> 07:46.840 use the Python-in-spec module, okay, in there, this building module in there. So, if you 07:46.840 --> 07:52.840 actually paste that, paste the function, like previously, and you can actually, if you 07:52.840 --> 07:59.840 actually use that, instant module and get the stack, you can understand that, which function 07:59.840 --> 08:04.840 is actually calling that, okay, and from which line is this actually calling, okay. 08:04.840 --> 08:10.840 So, in that way, you will actually get it very easily, that from where this function is 08:10.840 --> 08:15.840 being called, so you can both there and fix that, okay, rather than finding air and 08:15.840 --> 08:25.840 there and everywhere, okay. So, this is the thing that is about the debugging, okay. 08:25.840 --> 08:33.840 So, after debugging, we actually have like a hot fix, okay. So, the thing is that, as I actually 08:33.840 --> 08:40.840 say earlier, that, you should never do this in production, okay, unless you do, you know 08:40.840 --> 08:49.840 what you are doing, okay. So, so, but as you are engineer, we need to handle the production 08:49.840 --> 08:53.840 issue, hot fix, there is the name everything, like there are some downtime in there, and 08:53.840 --> 08:59.840 you need to fix something, you need to make something very emergency in this case, okay. 08:59.840 --> 09:05.840 So, there is the fastest way to do that is actual monkey patching, okay. If actually, 09:05.840 --> 09:12.840 using third-party package, there is some bug, and you want to fix that, and you want 09:12.840 --> 09:19.840 to fix that and make a like a hot fix in there. So, it is very, it is a best way to do 09:19.840 --> 09:26.840 is actual monkey patching. In the later, after the service went, goes up, you can actually, 09:26.840 --> 09:32.840 you can actually change the monkey patching to the actual fix in the library and make a 09:33.840 --> 09:38.840 pull request or use your own version in there, and maybe find some other solution in there. 09:38.840 --> 09:44.840 But, for emergency things, maybe you can actually push some monkey patch code in the production, 09:44.840 --> 09:51.840 okay. So, let me show you some pod example in there. 09:51.840 --> 10:14.840 Can you see this? Yeah, is it okay? Okay. So, this is the one example about the hot 10:14.840 --> 10:24.840 fix, okay. So, this is one example of the hot fix, okay. So, thinking about the situation 10:24.840 --> 10:31.840 like you actually have, I have upgraded the package, okay. So, you have added the package in 10:31.840 --> 10:37.840 your, in the old package, you actually, there are other, you were calling a function, okay. 10:37.840 --> 10:43.840 So, in the function, the one of the parameter was actually not required, okay. So, it was 10:43.840 --> 10:56.840 only divided default none or something like that, okay. But, but in the, in the new module, in the 10:56.840 --> 11:04.840 upgraded one, the function, the AG is actually required, like the variable is actually required 11:04.840 --> 11:10.840 in there, okay. So, what you can actually do is that actually already have upgraded the package, 11:10.840 --> 11:15.840 which the code in the production and the service went down because this is actually asking 11:15.840 --> 11:25.840 about the required argument in there, okay. So, let us see the example. 11:25.840 --> 11:48.840 Let us see, let us try hot fix, okay. If we run the hot fix that one pi, it will actually 11:48.840 --> 11:53.840 give this kind of error, okay. And this kind of error is actually very common in production 11:53.840 --> 11:58.840 system and everything, okay. In the, if you have to upgrade a package and you actually required 11:58.840 --> 12:03.840 a required argument, this kind of error actually very popular in there, okay. So, what you can actually 12:03.840 --> 12:11.840 do is that you can actually monkey pass it out and fix that as well, okay. So, you can actually, 12:11.840 --> 12:17.840 you can actually write a function, okay. In the, in the function, you actually actually 12:17.840 --> 12:24.840 import the module and after you actually import the module, you need to get the old function 12:24.840 --> 12:30.840 old function in the variable, okay. If the every function and everything is object in Python, 12:30.840 --> 12:34.840 you can actually, you keep that in a function in there, okay. Then you can actually write 12:34.840 --> 12:39.840 your own function that actually takes only two argument, the first name and last name, okay. 12:39.840 --> 12:46.840 And then you can pass the AG as none to this old function, okay. And you can actually monkey pass 12:46.840 --> 12:53.840 this new module with gate person, with your own gate person function. So, it will only 12:53.840 --> 12:59.840 take two argument in there, two keyword argument, not three. So, and you need to monkey 12:59.840 --> 13:06.840 pass it before importing, okay. So, after you actually import the function and make the object 13:06.840 --> 13:15.840 in there, this will actually work. You see, this one actually worked, but the previous 13:16.840 --> 13:21.840 one didn't work. The same module and everything, but only as we are actually doing the monkey 13:21.840 --> 13:26.840 patching thing in here, this one actually worked. And this is the simple fix. We, you will need 13:26.840 --> 13:31.840 five minutes, particularly fix that, rather than like downloading the package, fixing that, 13:31.840 --> 13:40.840 making a full request or maybe, downloading the detail of everything, okay. 13:40.840 --> 13:50.840 So, this is another example in here, okay. So, this is another example. So, after you actually 13:50.840 --> 13:59.840 upgrade the package, sometimes, sometimes, there are like, sometimes, there are like new, 13:59.840 --> 14:07.840 there are, there are new fix ways, that's in, that's in, that's in, that's in the package, 14:07.840 --> 14:12.840 that's in the low level package, but not in the high level package in there. You have 14:12.840 --> 14:17.840 not upgraded the high level package. You have upgraded the low level package in there, okay. 14:17.840 --> 14:23.840 So, in that case, what we are actually going to do, because you need the low level package 14:23.840 --> 14:28.840 for other things, but you also need, you cannot actually upgrade the high level package in there. 14:28.840 --> 14:34.840 Okay. So, you can actually monkey pass this low level package, so that the high level package 14:34.840 --> 14:42.840 actually calls that, this, this will actually, this will not result in a row, okay. 14:42.840 --> 14:53.840 So, if you see this, this low level package, okay. So, in the person, okay, we have a 14:53.840 --> 14:58.840 like function name, get upper full name, okay, and get upper full name actually calls the 14:58.840 --> 15:05.840 self-fast name, upper and self-fast name, upper, okay. But in our code, maybe there are some 15:05.840 --> 15:13.840 H cases and maybe in the database, we have null values, that, because of the, because of 15:13.840 --> 15:18.840 that reason, maybe the null value is actually coming for first name and last name, okay. 15:18.840 --> 15:25.840 So, this may actually give some error in there. 15:25.840 --> 15:40.840 You see, so this is the very common during the production, that non-type object has no 15:40.840 --> 15:45.840 attribute upper or something like that, okay. So, because you are actually passing the non-type, 15:45.840 --> 15:50.840 it cannot actually make it upper and give you the actual level. So, what you can actually 15:50.840 --> 15:57.840 do is that, you can actually also monkey page this, you can also monkey page this, like 15:57.840 --> 16:03.840 you can actually, this get function, like get person function, okay. In the, in the get person 16:03.840 --> 16:08.840 function, you can actually see that if it first name is non, you can actually return a like 16:08.840 --> 16:14.840 blank value, if the last name is non, you can also return a blank value, okay, rather than 16:14.840 --> 16:21.840 non, okay. So, in that case, this will also also fix your production issues. 16:21.840 --> 16:32.840 You see, so we are actually passing only the first name, as we are passing only the first 16:32.840 --> 16:39.840 name, it will actually only work, okay. So, the best way to do this kind of fixes is actually, 16:40.840 --> 16:45.840 it is not a best way, okay. But in the monkey page, this is the best way, okay. So, what 16:45.840 --> 16:51.840 you can actually do is that, you can actually create a new class in it in this main class, 16:51.840 --> 16:56.840 okay. So, in the main class, in the inherited class, you can actually fix this issue, okay. 16:56.840 --> 17:01.840 It is the first name is non, you can actually make it blank, it is the last name is non, 17:01.840 --> 17:06.840 you can actually make it blank, okay. And then you can actually do that, and you can actually 17:06.840 --> 17:15.840 just, in the module, okay, from where this class is imported, you need to patch at that module, 17:15.840 --> 17:21.840 okay. Not where the class is actually belong to, which is the file, okay. So, in 17:21.840 --> 17:31.840 it to patch, where from where this person, this class is being imported, okay. So, you can actually 17:31.840 --> 17:38.840 type in the old module, you can just, you can just patch this person, person in here, 17:38.840 --> 17:43.840 and it will actually, it will actually be the new person in here and it will actually fix 17:43.840 --> 17:56.840 your issue. You see, it is fixed, okay. Even though the main module, the old module 17:56.840 --> 18:05.840 has some issues, old module have the person with this issue, okay. And I am actually going 18:05.840 --> 18:11.840 to end with the one thing that is very nasty one, okay. So, you should never do that, okay, 18:11.840 --> 18:17.840 at first, first, first, but I am just showing it for research purpose, okay. So, this is the thing, 18:17.840 --> 18:24.840 okay. So, you do not want your application to have any call to Google.com. So, not your code, 18:24.840 --> 18:30.840 your code, not third-party code, not any code, okay. So, what you can, you can do is that, 18:30.840 --> 18:36.840 you can actually patch the request library, okay. You can patch the request library to get, 18:36.840 --> 18:44.840 to patch the gate, okay. You see, if this patch is the gate, and if the URL is Google.com, 18:44.840 --> 18:50.840 you can just like raise the connection URL, that it will not work. And this can be used in a very 18:50.840 --> 18:56.840 different way, and very unethical way, and very ethical way as well. And you can route these 18:56.840 --> 19:02.840 your traffic from one domain to another and anything. Sometimes, maybe you need to route from 19:02.840 --> 19:09.840 one domain to another domain for the whole project, okay. So, you do not want to change everywhere, 19:09.840 --> 19:16.840 you just change in a, in your based Python call, and it will actually work everywhere, okay. 19:16.840 --> 19:22.840 So, maybe you can actually patch the URL lib. So, even though who are not using the request library, 19:22.840 --> 19:33.840 can actually also benefit that, okay. So, let's see. You see, so the request is actually 19:33.840 --> 19:38.840 like failing. So, its overall project is actually, like, you cannot actually make a good 19:39.840 --> 19:45.840 fault to Google in there. So, if actually, make it as that, okay. So, let's all. 19:50.840 --> 19:55.840 Thank you. Do you have any question? 19:56.840 --> 20:01.840 Hello. 20:06.840 --> 20:15.840 Thank you. Very nice talk. So, quick, quick fixes, the get pushed into production often stay in production forever. 20:15.840 --> 20:22.840 What would you say, like, how is your experience with, like, linting, like an import 20:22.840 --> 20:29.840 in the middle of your file? Yes, is that better? 20:29.840 --> 20:35.840 With a monkey patch that gets into production is probably going to cause linting warnings. 20:35.840 --> 20:41.840 Like, how do you handle your linting warnings in projects? You're going to suppress just like, 20:41.840 --> 20:46.840 what that one line, this temporary fix is here forever, shush, or, yeah. 20:46.840 --> 20:51.840 So, the thing is that you can actually feed that in a very different way, okay. 20:51.840 --> 20:57.840 You can actually feed that in the main code base and maybe you can actually create another class in there. 20:57.840 --> 21:01.840 But sometimes you have no access to that specific package, okay. 21:01.840 --> 21:07.840 Like, you are using one package, that one is calling another package, and that one is calling another package. 21:07.840 --> 21:11.840 Okay. So, in that case, this one is the, like, super-fastest way. 21:11.840 --> 21:16.840 We just fixed that, there is specific package that is going to happen in the bug, 21:16.840 --> 21:19.840 and all the change is actually fixed. 21:19.840 --> 21:22.840 Do you worry about the debt with the... 21:22.840 --> 21:29.840 Yeah, it's a hot fix, okay. You always need to make a good fix after this hot fix after the system gets up. 21:29.840 --> 21:33.840 You always need to do a good fix in there. 21:33.840 --> 21:36.840 You should not keep that in your code base long time, okay. 21:36.840 --> 21:39.840 Okay, yeah, thank you very much. 21:39.840 --> 21:42.840 Another question? 21:44.840 --> 21:45.840 Hello. 21:45.840 --> 21:47.840 Can you hear him? Oh, yes. 21:47.840 --> 21:52.840 So, you've talked about monkey patching, pushing that code. 21:52.840 --> 21:58.840 So, sorry, just try and get out of the way. 21:58.840 --> 22:03.840 So, you've talked about writing monkey patches that you then, like, push to your repository, 22:03.840 --> 22:07.840 and then, like, sort of update your container, you know, rebuild stuff. 22:07.840 --> 22:16.840 Have you, have any experience with literally live patching the code in running processes, like, in production? 22:17.840 --> 22:22.840 So, in that case, if you actually pay as the code directly into the production in the code base, 22:22.840 --> 22:25.840 if you're actually using dog car, if you actually get a new build, 22:25.840 --> 22:29.840 if you actually just not exist there, okay. 22:29.840 --> 22:33.840 So, so, it is possible. 22:33.840 --> 22:39.840 I'm here to plug, like, a tool called pyrocyte, like pyrocyte is about pyrocyte, 22:39.840 --> 22:42.840 so you can get, like, the live python shell into your thing. 22:42.840 --> 22:47.840 It's the last thing you should do, but it is really, really helpful if, like, your thread is blocked, 22:47.840 --> 22:50.840 and it's not getting any debug, say, that kind of thing. 22:50.840 --> 22:53.840 You can literally change anything in the process. 22:53.840 --> 22:54.840 I'll do it. 22:54.840 --> 22:55.840 Cool. 22:57.840 --> 22:59.840 I'm on the question. 22:59.840 --> 23:00.840 Oh, yeah. 23:00.840 --> 23:10.840 Yeah, it's not exactly a question. 23:10.840 --> 23:16.840 I would say, before trying all these things, there are other options. 23:16.840 --> 23:18.840 For example, you gave the example of tracing. 23:18.840 --> 23:23.840 Python has a built in library called trace inside the standard library. 23:23.840 --> 23:26.840 That helps with state tracing. 23:27.840 --> 23:31.840 Similarly, for monkey patching, I would also say, if you really have to do it, 23:31.840 --> 23:36.840 then use the unit test mock patch, you know, then doing it yourself. 23:36.840 --> 23:41.840 So, in the unit test mock patch, it's actually based mostly on unit test use case, okay. 23:41.840 --> 23:45.840 And this is for the, like, basic use case in there, okay. 23:45.840 --> 23:50.840 And yes, there are a lot of ways to do that, and for the python tracing, 23:50.840 --> 23:56.840 but you cannot actually add a debugger to a specific package in the local machine, 23:56.840 --> 23:58.840 or maybe in the production, okay. 23:58.840 --> 24:02.840 So, it's quite difficult to actually add a specific debugger to actually, 24:02.840 --> 24:05.840 a third-party package in this specific line in there. 24:05.840 --> 24:09.840 So, you can actually debug that, what value is actually getting, 24:09.840 --> 24:11.840 and you can actually fix that in there, okay. 24:11.840 --> 24:15.840 Maybe the thing is actually not reproducible in your local machine, 24:15.840 --> 24:17.840 but it's actually happening in the production, okay. 24:18.840 --> 24:21.840 So, these things actually get complicated in there. 24:25.840 --> 24:27.840 Another one? No? Okay. 24:27.840 --> 24:28.840 Thank you so much. 24:28.840 --> 24:29.840 Thank you, everyone. 24:34.840 --> 24:36.840 Next speaker will be,