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:08.840 --> 14:12.840 that's in the low level package, but not in the high level package in here. You have not 14:12.840 --> 14:17.840 upgraded the high level package, you have upgraded the low level package in here, okay. 14:17.840 --> 14:23.840 So, in that case, what we're actually going to do, because you need the low level package 14:23.840 --> 14:27.840 for other things, but you also need, you cannot actually upgrade the high level package in 14:27.840 --> 14:33.840 there, okay. So, you can actually, monkey pass this low level package, so that the high 14:33.840 --> 14:41.120 the high level package actually calls that, this will actually, this will not result in 14:41.120 --> 14:54.360 error. So, if you see this, this low level package. So, in the person, we have a function 14:54.360 --> 15:00.000 name get upper full name and get upper full name actually calls the self first name 15:00.000 --> 15:07.480 upper and self last name upper. But, in our code, maybe there are some H cases and maybe 15:07.480 --> 15:15.860 in the database, we have null values that, because of the, because of the reason, maybe the 15:15.860 --> 15:20.760 null value is actually coming for first name and last name. So, this may actually give 15:20.760 --> 15:37.600 some error in there, you see. So, this is the very common 15:37.600 --> 15:43.640 error in the production that, non type object has no attribute upper or something like that. So, 15:43.640 --> 15:48.640 because you are actually passing the non type, it cannot actually make it upper and give 15:48.640 --> 15:52.320 you the actual level. So, what you can actually do is that, you can actually also 15:52.320 --> 16:00.640 monkey page this, you can also monkey page this, you can actually, this get function like get 16:00.640 --> 16:06.440 person function, in the get person function, you can actually see that, if it first name is 16:06.440 --> 16:12.320 non, you can actually return a like blank value, if the last name is non, you can also 16:12.320 --> 16:20.120 return a blank value rather than non. So, in that case, this will also also fix your production 16:20.120 --> 16:32.120 issues, you see. So, we are actually passing only the first name, as we are passing only 16:32.120 --> 16:39.720 the first name, it will actually only work. So, the best way to do this kind of fixes is 16:39.720 --> 16:46.280 actually, it is not a best way, but in the monkey page, this is the best way. So, what you 16:46.280 --> 16:53.520 can actually do is that, you can actually create a new class in it in this main class. So, 16:53.520 --> 16:58.080 in the main class, in the inherited class, you can actually fix this issue, this is the first 16:58.080 --> 17:02.640 name is non, you can actually make it blank, if the last name is non, you can actually make 17:02.640 --> 17:09.320 it blank and then you can actually do that. And you can actually just in the in the 17:09.320 --> 17:18.320 one module, from where this class is imported, you need to patch at that module, not where 17:18.320 --> 17:24.000 the class is actually belong to, which is the file. So, you need to patch, where from 17:24.000 --> 17:34.000 where this person, this class is being imported. So, you can actually in the old module, 17:34.080 --> 17:41.680 you can just patch this person in here and it will actually, it will actually be the new 17:41.680 --> 17:54.680 person in here and it will actually fix the issue. You see, it is fixed, even though 17:54.680 --> 18:00.880 even though the main module, the old module has some issues, old module have the person 18:01.040 --> 18:08.040 with this issue. And I am actually going to end with the one thing, that is very nasty 18:08.040 --> 18:15.320 one. So, you should never do that at first first, but I am just showing it for research 18:15.320 --> 18:21.640 purpose. So, this is the thing. So, you do not want your application to have any 18:21.720 --> 18:29.720 call to Google.com. So, not your code, not third part code, not any code. So, what you 18:29.720 --> 18:36.400 can do is that, you can actually patch the request library, you can patch the request library 18:36.400 --> 18:45.080 to get to patch the gate. You see, if this patch is the gate and if the URL is Google.com, 18:45.080 --> 18:50.760 you can just like raise the connection row, that it will not work. And this can be used in 18:50.920 --> 18:56.280 a very different way and very unactical way and very ethical way as well. And you can 18:56.280 --> 19:01.480 to route this, your traffic from one domain to another and anything. Sometimes, maybe you 19:01.480 --> 19:08.680 need to route from one domain to another domain for the whole project. So, you do not want 19:08.680 --> 19:14.920 to change everywhere, you just change in the in your based Python call and it will actually 19:15.000 --> 19:21.000 work everywhere. So, maybe you can actually patch the URL leap. So, even though who 19:21.000 --> 19:28.040 are not using the request library, can actually also benefit that. So, let us think, you see. 19:32.600 --> 19:38.600 So, the request is actually like failing. So, its overall project is actually like, you cannot 19:38.680 --> 19:44.920 actually make a good fall to Google in there. So, you actually make it as that. So, let us all. 19:51.000 --> 19:55.800 Thank you. Do you have any question? 19:56.120 --> 20:13.960 Well, thank you very nice talk. So, quick, quick fixes the get pushed into production 20:13.960 --> 20:20.360 often stay in production forever. What would you say? How is your experience with like, 20:20.360 --> 20:27.400 linting like an import and the middle of your file? Can you put it? Oh, yes, is that better? 20:30.120 --> 20:35.800 With a monkey patch that gets into production is probably going to cause linting warnings. 20:35.800 --> 20:41.640 Like, how do you handle your linting warnings in projects? Are you going to suppress just like 20:41.640 --> 20:48.200 what that one line? This temporary fix is here forever. Shush or yeah. So, the thing is that 20:49.160 --> 20:53.720 you can actually see that in a very different way. You can actually see that in the main code 20:53.720 --> 21:00.200 base and maybe you can actually create another class in there. But sometimes you have no access to 21:00.200 --> 21:06.280 that specific package. Like, you are using one package, that one is calling another package and 21:06.280 --> 21:11.880 that one is calling another package. So, in that case, this one is the like super fasted way. 21:12.040 --> 21:18.040 We just fix that, there is specific package that is going to happen in the bag and all the chain 21:18.040 --> 21:27.000 is actually fixed. Do you worry about the tech? Yeah, it is a hot fix. You always need to make 21:27.000 --> 21:33.640 a good fix after this hot fix after the system gets up. You always need to do a good fix in there. 21:33.640 --> 21:38.520 You should not keep that in your code based on time. Okay, yeah, thank you very much. 21:38.520 --> 21:51.400 Another question? Can you hear me? Oh, yes. So, you've talked about monkey patching, pushing 21:51.400 --> 22:01.400 that code. Sorry, just try and get out of the way. So, you've talked about writing monkey 22:01.400 --> 22:08.040 patches that you then push to your repository and then update your container, rebuild stuff. 22:08.680 --> 22:14.600 Have you have any experience with literally live patching the code in running processes? 22:15.640 --> 22:21.240 Like, in production. So, in that case, if you actually pay as the code directly into the 22:21.240 --> 22:24.840 production, in the code based, if you're actually using dog car, if you actually get a new 22:24.840 --> 22:35.480 build, if you actually just not exist there. Okay, so. So, so, it is possible. I'm here to plug 22:35.560 --> 22:41.800 like a tool called pyrocyte, like pyrocyte that's about pyrocyte, so you can get like the live 22:41.800 --> 22:46.360 python shell into your thing. It's the last thing you should do, but it is really, really helpful 22:46.360 --> 22:51.480 if your thread is blocked and it's not getting any debug, say, that kind of thing. You can 22:51.480 --> 22:55.880 literally change anything in the process. I'll do it. Cool. 22:56.200 --> 23:00.520 Any other question? 23:08.520 --> 23:14.200 Hi, yeah, it's not exactly a question. I would say, before trying all these things, 23:16.120 --> 23:21.080 there are other options, for example, you gave the example of placing python as a built-in 23:21.400 --> 23:28.360 library called trace inside the standard library, that helps with straightest tracing. Similarly, 23:28.360 --> 23:33.400 for monkey patching, I would also say, if you really have to do it, then use the unit test 23:34.520 --> 23:38.280 marked patch, you know, that's doing it yourself. So, in the unit test marked patch, 23:38.280 --> 23:44.360 is actually based mostly on unit test use case, okay, and this is for the like basic use case in 23:44.360 --> 23:50.840 there. Okay, and yeah, there are a lot of ways to do that, and for the python tracing, 23:50.840 --> 23:57.640 but you cannot actually add a debugger to a specific package in the in the local machine or maybe 23:57.640 --> 24:02.680 in the production. Okay, so it's quite difficult to actually add a specific debugger to actually 24:03.320 --> 24:08.280 the third-party package in this specific line in there. So, you can actually debug that what 24:08.280 --> 24:13.960 value is actually getting, and you can actually fix that in there, okay, maybe the thing is actually 24:13.960 --> 24:18.440 not reproducible in your local machine, but it's actually happening in the production. Okay, 24:18.520 --> 24:21.320 so this thing is actually gets complicated in there. 24:25.560 --> 24:29.320 Another one? Nope. Okay, thank you so much. Thank you everyone. 24:34.840 --> 24:35.960 Next speaker will be