Avoiding import loops in Python

  Рет қаралды 95,326

mCoding

mCoding

Күн бұрын

Пікірлер: 192
@Bekonisko
@Bekonisko 3 жыл бұрын
You know you royally f-ed up when the tutorial expert tells you "In this case, I cannot help you, good luck" :P
@daviddunleavy187
@daviddunleavy187 3 жыл бұрын
You are the only channel that I feel makes quality tutorials for the sort of stuff that is a tad more advanced/a bit below the surface in python. I always learn something even when the video is a topic that I think I already have a pretty good handle on. Thanks!
@nathanoy_
@nathanoy_ 2 жыл бұрын
fully agree^^
@pranavnyavanandi9710
@pranavnyavanandi9710 2 жыл бұрын
mCoding is like the Stack Overflow of KZbin. 😄
@Zokrar
@Zokrar 3 жыл бұрын
"Your application needs some SERIOUS redesigning, it's going to be a mess no matter how you do it" Somehow hearing James say this is even worse than "I'm not mad, I'm disappointed" from a parent
@mCoding
@mCoding 3 жыл бұрын
Everyone writes bad code sometimes! I would never be disappointed as long as you recognize the error and *learn* from it.
@YeOldeTraveller
@YeOldeTraveller 3 жыл бұрын
@@mCoding I once had an instructor in a Computer Science course state they he never wrote bad code. I switched to a new section the next day. He had just told me he did not write code. (Or he was lying)
@ChristianBrugger
@ChristianBrugger 3 жыл бұрын
@@YeOldeTraveller In a univeristy setting, his statement makes sense to me. What I have seen is that 25% of the students don't get coding and write code so bad that it is really shocking. And he probably never wrote code of such quality. I think that is what he is referring to. James is referring to something completely different. Writing code that you find deeper into the project bad. This happens to everyone. The former not always.
@Mutual_Information
@Mutual_Information 3 жыл бұрын
I had this problem a few months back and when asking coworkers for how they solved, no one had good answers. Everyone seems to just guess around until things works. Nice to have a solution like this.
@mCoding
@mCoding 3 жыл бұрын
Feel free to share this video with all your coworkers!
@theepicguy6575
@theepicguy6575 3 жыл бұрын
HOW!, such perfect timing, been breaking my head for the past few days over a circular import!
@mCoding
@mCoding 3 жыл бұрын
Hope this helps you resolve it!
@theepicguy6575
@theepicguy6575 3 жыл бұрын
@@mCoding yup, instantly solved 50% halfway thro the video, just TYPE_CHECKING for one, and some dynamic imports :3
@hellNo116
@hellNo116 3 жыл бұрын
i love that you closed the video with exactly the phrase any sane person would give to someone who loyally screwed up and you didn't sugar quoted.
@robmckiernan3264
@robmckiernan3264 3 жыл бұрын
😅 Sugar quoted. Sugar coat it
@mCoding
@mCoding 3 жыл бұрын
Sometimes that's the way it goes, better to recognize it and do what you can to move on!
@ShiroMZM
@ShiroMZM 3 жыл бұрын
Wish I've seen this some months ago. I did the "serious" re-design because of type checking. never the lesss, I did end up with a module design that's quite complete so that's a win :D
@QuantumHistorian
@QuantumHistorian 3 жыл бұрын
I think gold rule is: _Don't have code in one module that runs code from another module at import time_ . The only reasonable exception to this rule for libraries, IMO, is if you have one module that defines classes that inherit from another module. In this case, you have to divide the various classes in the inheritance chain between different modules in a sensible way.
@mCoding
@mCoding 3 жыл бұрын
Great tip! I want to emphasize that I agree that the best thing to do is avoid running code at import time in the first place.
@QuantumHistorian
@QuantumHistorian 3 жыл бұрын
@@mCoding Sure, except that for running things like function and class definitions (and class attributes) it's utterly unavoidable. But the only one of those that has any business importing from other modules are parents in class definitions. And maybe decorators in some cases.
@xelaxander
@xelaxander 3 жыл бұрын
@@mCoding Oh god yes! I came across a project that did this recently. The authors just loaded ~10GB from disk, reformatted the data and dumped it again.
@megaing1322
@megaing1322 3 жыл бұрын
I can't really a situation where the last example you showed is relevant, but there is one general fix you can try: moving the `from ... import ...` statements, and everything that directly depends on them at import time at the end in both files. While that violates PEP-8, it often works. This is also a quick fix for almost all the other situations you mentioned.
@naalul
@naalul 3 жыл бұрын
Another way would be to extract whatever is the reason for the circular import (in this case module_b.func_b2 that depends on module a) to a third module
@AntonioMellor
@AntonioMellor 2 жыл бұрын
Thank You! I know this vid is older but it popped up as recommended so I watched it a week ago I think. Today I had this exact problem with type hinting and I remembered this video. some of the best Python content being made!
@anatolytsi
@anatolytsi 3 жыл бұрын
Had a circular import error just yesterday, very relevant :) Had a loader script, which would store the class type of other module class that inherits from other script class, which in turn was using global variables from loader script. Fixed by moving the globals to a separate script file accessible for every script It is definitely an architectural problem most of the time :)
@sohangchopra6478
@sohangchopra6478 3 жыл бұрын
You might want to consider getting rid of globals entirely - they are (generally) a bad idea. Note: By globals, I mean global mutable variables, not constants (which are never mutated after assignment).
@anatolytsi
@anatolytsi 3 жыл бұрын
@@sohangchopra6478 sorry, my bad, I meant constants, of course :) Completely agree on your statement and never use global variables
@liude7765
@liude7765 3 жыл бұрын
Generally, circular dependencies are a sign of bad design, with at least one principle being violated, most often those of single responsibility, low coupling, and layering. This might be ok for small applications, and might not lead to problems right away even in larger ones, but over time as the system grows it's bound to lead to issues. The worst part is, in circumventing these issues developers often introduce worse and worse patterns, eventually leading to largely unmaintainable systems and mountains of spaghetti code. If you're running into issues like this, some architectural redesigns are definitely needed, and should be done sooner while the codebase is small rather than later if the project is intended to be a sustainable long-term.
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
Cough Selenium Cough
@PatriciaOsifo
@PatriciaOsifo 2 жыл бұрын
@Liude, could perhaps suggest some resources to learn about design principles or best design architectures? For me, I was working on a task that required a certain program structure. I submitted something with a different but I think, better structure, but it was rejected. So, I needed some way for the app to work without errors in that structure. And this was really helpful for that. Sometimes, we can help what the client wants.
@jakobullmann7586
@jakobullmann7586 2 жыл бұрын
@@PatriciaOsifo Cycles are pretty evil. JetBrains IDEs have a function to visualize dependency matrices. No cycles means the matrix should be lower-triangular. As a rule of thumb, lower level functionality should be independent of higher level functionality (and if A depends on B and B depends on C, try to make A to depend on C only through B). If you cannot avoid cycles, at least keep it to class cycles and avoid module cycles at all cost, because they will make refactoring impossible. Static analysis tools like SonarQube can also help. Otherwise I’d recommend read about clean code and software architecture.
@PatriciaOsifo
@PatriciaOsifo 2 жыл бұрын
@@jakobullmann7586 Thanks a lot for this!
@NicolasChanCSY
@NicolasChanCSY 2 жыл бұрын
I am working on a Selenium automation project recently and I use page object model ("POM") to manage the different pages. Since POM encourages page objects to return another page object when navigating to another page, I run into circular import, when two pages navigate bidirectionally. Glad that I remember that I saw this video a few months ago and can come back for your great tips and insights! Now I understand the issue better. In my case, I shall use your suggestion in video chapter "Subpackage init cycle" with the interface directories. Thanks again!
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
Selenium itself is a mountain of spaghetti code. My script suddenly started taking 45 seconds to load and I didn’t change anything .
@NicolasChanCSY
@NicolasChanCSY 2 жыл бұрын
@@drygordspellweaver8761 I just treat it as a black box when using it 😁. However, sometimes, I do hope that Selenium can have clearer documentations. And most StackOverflow answers are using Selenium
@DanielLavedoniodeLima_DLL
@DanielLavedoniodeLima_DLL 2 жыл бұрын
I remember that Flask had some kind of circular dependency issue when you try to separate the project into an MVC architecture with multiple unit components in different folders. I used it more often a few years ago, not sure if they overcame that issue in the newer versions
@mCoding
@mCoding 2 жыл бұрын
I know exactly what you mean and no they have not solved this. It's not really something they can solve bc at its heart the issue is that the shortest simplest way to build an application that they encourage in all their examples naturally leads to cyclic dependencies if your application gets even slightly larger. The real solution is to encourage users to not use global variables for defining all their views/blueprints and instead keep everything inside functions and use locals. It's may look like "more work" and "not as pretty" and "over engineered" but trust me it will save you many hours in the long run!
@MechMK1
@MechMK1 2 жыл бұрын
I recall my professor saying "If Foo needs Bar and Bar needs Foo, then the two belong together. Who are you to separate two lovers?"
@taneliharkonen2463
@taneliharkonen2463 3 жыл бұрын
Simply the best video on utube on import loops! That was so thorough!! :o :D
@barterjke
@barterjke 2 жыл бұрын
When i starting to feel that i know everything about python, your chanel come and crush my confidence.
@sebastiangarciaacosta5468
@sebastiangarciaacosta5468 3 жыл бұрын
I love you, thanks for all the great content.
@mCoding
@mCoding 3 жыл бұрын
Many thanks for the kind words!
@Scranny
@Scranny 3 жыл бұрын
Is it best practice when using type hints to *always* put the type imports under the "if TYPE_CHECKING" clause regardless of cyclical imports? (For purposes of readability and a way to announce that those imports aren't importing any functionality?)
@mCoding
@mCoding 3 жыл бұрын
Great question! I personally do this out of habit, but I don't think I would call it a best practice so much as defensive programming.
@KappakIaus
@KappakIaus 3 жыл бұрын
I was looking for this question, nice :)
@hedwinbonnavaud6998
@hedwinbonnavaud6998 Жыл бұрын
Thanks a lot for this calm, clear, and complete tutorial
@richardcoppin5332
@richardcoppin5332 2 жыл бұрын
I'm my experience 'real' circular dependencies tell me that you probably need a third module (possibly containing an abstract base class). Out may not solve every issue, but is definitely worth exploring.
@arceusmewtwo7774
@arceusmewtwo7774 2 жыл бұрын
Thanks a lottt man , this helped me solve a major problem in my project (application)!! I'll definitely mention u in the credit section of the application
@sawcondeez
@sawcondeez 3 жыл бұрын
Does Python reimport the module again when it is declared inside the function? From the video @ 2:02, does Python reimport func_b1 from module_b again when func_a is called the second time?
@brunoais
@brunoais 3 жыл бұрын
No. Python caches imports by default. You can use internal APIs to order python to forget a cached import, though.
@kelpie6902
@kelpie6902 Жыл бұрын
This is so unbelievably helpful
@HadesMrDark
@HadesMrDark 2 жыл бұрын
This was a great watch, thank you so much, for sharing with us your knowledge.
@jurgenrusch4041
@jurgenrusch4041 3 жыл бұрын
Hi, I love your channel and I wish this video on circular imports had been there 2 years ago when I was struggling with exactly the topics you have treated here. Thanks for the clear explanation. And keep those videos coming!
@yash1152
@yash1152 8 ай бұрын
5:31 where is main.py residing?? i cant figure it out in this project view of jetbrains ides pycharm
@ChristianBrugger
@ChristianBrugger 3 жыл бұрын
Great video. Didn't know the trick with the interface module. Saw it on some open-source projects and was wondering why thy do it.
@mCoding
@mCoding 3 жыл бұрын
Glad you liked it! Some packages also use the "module" vs "_module" naming convention for having a native C module with the underscore and no underscore for the interface. This is seen a lot in CPython standard library itself.
@fat_pigeon
@fat_pigeon 3 жыл бұрын
Another technique if your dependency is needed only inside a function is dependency injection. e.g. ``` from . import logging def foo() -> None: logging.log("foo") ``` => ``` from typing import Callable def foo(log : Callable[[str], None]) -> None: log("foo") ```
@amgg_
@amgg_ 3 жыл бұрын
something probably worth noting, instead of using `from __ future‌ __ import annotations` with `typing.TYPE_CHECKING` you can just manually make them strings (and in fact that's what you'll need to do if you're below 3.7)
@Scymet
@Scymet Жыл бұрын
It's ugly tho
@reddragon3132
@reddragon3132 3 жыл бұрын
In reference to the from __future__ import annotations, what determines the 'future'. Is this a feature that is currently scheduled to be in a future python release (or is in an already released later version)? In which case when will this annotation behaviour become the default?
@mCoding
@mCoding 3 жыл бұрын
docs.python.org/3/reference/simple_stmts.html#future-statements Typically yes. It is to allow opt-in changes that are backwards incompatible for things that are expected to become the default in future versions of Python. Though "expected" may change, as may be the case soon with annotations.
@lex_darlog_fun
@lex_darlog_fun 3 жыл бұрын
What about `__all__` for sub-package cycle ? You can have modules defined in `__all__` of package's init. That way you have both benefits: you can do `import *` while also avoiding a circular dependency.
@mCoding
@mCoding 3 жыл бұрын
The `__all__` variable won't help you avoid import cycles as it only affects what happens when you use "import *", whereas all the import cycles presented in the video don't even use "import *" at all. It could help you litter your namespace less than if you didn't use it when you "import *". However, it would still be better to just import the things you actually need.
@peter.wilson1
@peter.wilson1 2 жыл бұрын
The whole point behind modular boundaries is to say Is to guarantee that all resources needed are imported and are made to work in isolation relative it to it’s dependencies. So in the case of a module being a sub module it could make sense that you might want to reference the Ancestor modules, But what it seems to make more sense is that you were to have a module that specifically deals with that interrelationship an imported in both places. I think that would be a more stable solution that avoids breaking the dag model of modules. Another thing to avoid in general with most programming language is the concept of accessing global variables. Globals will get you every time. One problem with globals in most languages is you cannot guarantee their initialization order unless you’ve seen it yourself. If you do use a global variable and it’s in a separate compilation unit the loading sequence could be out of order in causing undefined behavior.
@zapshadab3450
@zapshadab3450 Жыл бұрын
Thank you for giving solution for these types of errors
@Articha
@Articha 3 жыл бұрын
I'm doing some pet-project, and met import cycle. Thanks, James Murphy, u nearly save my project
@Jmignet
@Jmignet 3 жыл бұрын
Great video! I was curious about your mention to "import time". I tried to google it, but Google thinks I am asking about the time library. is there any other terminology I could use to research that subjext?
@mCoding
@mCoding 3 жыл бұрын
By import time i just mean the time that a module is imported. This is when functions and classes are typically defined, rather than when you call your functions or create instances of your classes. The term import time is not formally defined, it's just a colloquial term.
@PatriciaOsifo
@PatriciaOsifo 2 жыл бұрын
This was really a lot of help! THANK YOU!
@aDifferentJT
@aDifferentJT 3 жыл бұрын
All of these violate layering and so I’d generally want to redesign all of these.
@mCoding
@mCoding 3 жыл бұрын
Hmm could you elaborate? An example might help me and other readers to understand your approach.
@Techiesse
@Techiesse 3 жыл бұрын
@@mCoding Divide the application in layers each with different levels of abstraction. At the bottom we have infrastructure functionality and at the top we have user interaction. The golden rule is: no layer is allowed to access anything from upper layers ( they can only look downwards). Ex: the code that writes a file to disk is not allowed to change the color of a button on the UI. If such a feature is needed it must be done via a callback.
@sohangchopra6478
@sohangchopra6478 3 жыл бұрын
@@Techiesse That sounds similar to how Computer Networks are designed - there are different layers (see OSI Network Model), each of which performs one type of task. The higher level ones depend on lower level ones.
@Techiesse
@Techiesse 3 жыл бұрын
@@sohangchopra6478 Yes, the difference is that in the OSI model each layer has a very specific role, while in application design the layers can be anything (I was not very accurate in my first explanation :) ) as long as they follow the rule. Usually they tend to fall in this infra -> UI paradigm and then become similar to network architectures.
@astronemir
@astronemir 3 жыл бұрын
@@Techiesse thank you this is really interesting. Is this a design pattern that one can read more about?
@mishikookropiridze
@mishikookropiridze 3 жыл бұрын
Interface module is interesting.
@tsunekakou1275
@tsunekakou1275 3 жыл бұрын
remind me of #include, the separation of declaration and definition in C and C++. I wonder what happened when C was designed back in the 70s and how C++ address this in C++20 module.
@mCoding
@mCoding 3 жыл бұрын
Indeed it was a similar problem that led to the separation of declaration and definition in C (can't define mutually recursive functions without forward declarations). As for C++, C++20 modules are "imported" at compile time, so any cycles are resolved before runtime.
@nickgood6088
@nickgood6088 2 жыл бұрын
I don't get the part where modules depend on their __init__ files, does anyone know the subtley of that? It's not like the modules are importing their init right?
@baronbacku9984
@baronbacku9984 3 жыл бұрын
i love this channel so much
@namdao2672
@namdao2672 Жыл бұрын
i'm straight up putting this in my bookmark
@davea136
@davea136 Жыл бұрын
When James says "Good luck" that means "don't do this." Listen to him.
@not_vinkami
@not_vinkami 3 жыл бұрын
Will importing at runtime be slow? I feel like that is clean to use but I'm a bit afraid of its consequences in execution time
@mCoding
@mCoding 3 жыл бұрын
Imports are cached in sys.modules so the runtime import will only actually run once, meaning there will be no meaningful difference in execution time from executing the function many times.
@not_vinkami
@not_vinkami 3 жыл бұрын
@@mCoding oh that's nice! I thought I'd need to manually cache the module somehow. I love Python
@johnnytoobad7785
@johnnytoobad7785 3 жыл бұрын
I first had this problem while writing python back-end code for a tkinter based gui-app. The main gui mod was "importing" back-end (command-button callback) code. No problem. However I also needed to update gui attributes from the back-end import. (ex. a status message line) I attacked this problem by loading the gui widget ref's into a dict which gets copied (loaded) to the back-end import from the main gui driver module, just after the gui performs its own initialization. Now the back end has access to ALL public gui attributes via the individual gui widget refs from the copied dict. BUT...You need to null out these extra (back-end) ref's BEFORE the main gui widgets get destroyed. You can use this technique for any type of "object" (defined in the driver module) that the "imported" module needs to access. It's kind of indirect but it works just fine. In this case the dict.-of-widget-refs acts as the "interface".
@mCoding
@mCoding 3 жыл бұрын
Thanks for sharing!
@johnbennett1465
@johnbennett1465 3 жыл бұрын
Having had some nasty cyclical dependencies, here is a last resort method that can resolve some types of loops. - Remove the import of A from B - A imports B - Finishes initializing itself - At the end pokes its needed members into B - Finally it calls an initialization function in B that allows it to fix up any dependencies on A This is extremely ugly and should only be used when cleaner options won't work. I have been backed into this corner once. I tried several other options, but in the end this was the only way I could get it to work.
@mCoding
@mCoding 3 жыл бұрын
Hey, it's not always feasible or worth your time and effort to fix old code (that may not even be written by anyone still around). Do what you gotta do and if a quick and dirty fix does the job, that might be the right answer for your situation.
@ManuelBTC21
@ManuelBTC21 3 жыл бұрын
Rules of thumb: - Only import modules directly `import x.y` - For common imports, shorthands `import x.y as z` can make sense - For common types create a module project/common_types.py and import with `import project.common_types as ct`
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
And if the module you’re importing is enormous? Say, Selenium or Tensorflow
@sergio20r
@sergio20r Жыл бұрын
I'm a beginner at programming. There's something about TYPE_CHECKING that I didn't fully understand and hopefully you could help me: We are still importing class B from module_b and then class A from module_a so tecnically the code will still crash, right? Or it won't since it's purely a test with mypy?
@youcamp132
@youcamp132 2 жыл бұрын
I'm new to python so this might be a stupid question. Why wouldn't you just check if the module is already imported before importing it? As in this example: if 'ModuleName' not in dir(): import ModuleName Which also raises the question why doesn't import do that automatically? Am I missing something?
@mCoding
@mCoding 2 жыл бұрын
Python does check if a module is already imported before importing it. The issue here with import loops is when you try to grab a value out of a module that has not finished importing when the value has not yet been defined in the module.
@youcamp132
@youcamp132 2 жыл бұрын
@@mCoding Ah okay, good to know. I was missing something. And thank you for your response.
@yash1152
@yash1152 8 ай бұрын
7:58 hmm, a yet another new thing specifoc to packaging learnt interface packages with no modules, but defining inits
@kennyostrom3098
@kennyostrom3098 2 жыл бұрын
I just saw this video. Regarding the runtime import inside a function, pep8 and pylint hate that idea. Any thoughts on why, and why is it okay in this case? You do avoid the issue using the other option, but you lose the runtime benefit you mentioned. Nevertheless, I am uncomfortable with the style guide violations not even being mentioned.
@koenbrink
@koenbrink 3 жыл бұрын
Could I just ask, why isnt the "from module_a import something" just a thing the compiler uses to then read it as module_a.something every time 'something' is written in the file? Apparently a from statement is different, but I always thought it worked as I described above. Which begs the question: are from statements better in any way? (faster for example), otherwise, there is literally no reason to not convert all from import statements to what I described so we never get these circular import errors right?
@alagaika8515
@alagaika8515 2 жыл бұрын
There is a slight performance penalty with writing module_a.something every time you use it instead of importing the name "something" directly (essentially the time it takes to look up a key in a dictionary). If you import a module, you have that module in your available names and can, at any time, look up names inside the module. If you directly import a specific name from a module, you have that specific name available and do not need to look it up anymore. (or, more specifically, you only need one lookup directly into globals() instead of one lookup into globals() to get the module and one lookup into the module to get the element).
@RoamingAdhocrat
@RoamingAdhocrat 2 ай бұрын
I got a very weird import issue yesterday - no error message but my tests failed with results like `AssertionError: assert MyObject(id=42) == MyObject(id=42)` where one was returned by the code under test and the other was made in the test function. making every __init__.py blank and using fully qualified imports fixed it. but I'm gonna use that interface subpackage idea
@Victor_Marius
@Victor_Marius 2 жыл бұрын
Is it any performance improvements in importing only a function / class instead of the entire module or benefits (excepting the fact that you won't have to prefix all your function calls from that module)?
@mCoding
@mCoding 2 жыл бұрын
When you import a single function, Python still imports the entire module it came from. The savings (miniscule) comes from the fact that when you do mod.func this is essentially a dictionary lookup of mod inside the current module then a ductionary lookup of func inside mod. Whereas if you bound func to the current module, then referring to func only incurs the name lookup of func inside the curent module, saving 1 dictionary lookup. This will be a pretty miniscule savings though and not a reason to do it one way or the other.
@psuw
@psuw Жыл бұрын
Awesome video. Sub guaranteed.
@mCoding
@mCoding Жыл бұрын
Much appreciated!
@markprado3759
@markprado3759 2 жыл бұрын
another way to fix this on top of my head, is to better setup the architecture of your file structure. i dont do chain imports, make sure all other module does not import each other. you should have entry point like app.py then you import a middle man module which does all your logic and from that middle man module you call the imports, and usually those modules are in separate bin/ folder. So the structure looks like this: app.py src/ - middle_man.py - bin/ -- mod_a.py -- mod_b.py
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
Yeah but then you’d end up with 3 or 4 middle man modules unless you want 15,000 lines of code in one module. Leading back to exactly the problem of circular imports.
@md2perpe
@md2perpe 3 жыл бұрын
Sometimes it can help moving import statements to the end of a file.
@mCoding
@mCoding 3 жыл бұрын
True true! People will wave PEP8 violations at you, but sometimes this is the easiest thing to do!
@bruradagast
@bruradagast 3 жыл бұрын
your last example with global variable is daily reality for anyone working with Flask or similar frameworks that heavily rely on function decorators that use global variables. So, did you just call all Flask ecosystem crappy code? :D seriously, thanks a lot for the video, very insightful!
@gregorymorse8423
@gregorymorse8423 3 жыл бұрын
Not mentioned: use the AST parser to write a program which generates a module import graph to detect most cases (non-dynamic load) circular imports with static analysis without running anything in huge projects even. You need to build a graph and do a depth first search or topological sort to check for cycles. How come such a simple python script doesnt exist? I wrote one to detect recursion, I might extend it fir this
@mCoding
@mCoding 3 жыл бұрын
It probably does exist 😅. If you do make one yourself be sure to check out the TopologicalSorter introduced in Python 3.9!
@arthurletrehumain
@arthurletrehumain 3 ай бұрын
If you want to define your class thought multiple files, consider using mixins
@mohsenhassani495
@mohsenhassani495 2 жыл бұрын
You are amazing man!
@mCoding
@mCoding 2 жыл бұрын
Thank you!
@XCanG
@XCanG 2 жыл бұрын
One method that is not mentioned here is creating *submodule* just for intersected functions of code, usually I name it like *util.py* What I do is put those intersected code in util submodule, then from both modules I import desired functions from util submodule. Since there is only one direction of importing, then there is no that kind of issue.
@acikast
@acikast 2 ай бұрын
great video, thanks a lot!
@abhi6853
@abhi6853 2 жыл бұрын
great video ,super explaination
@mCoding
@mCoding 2 жыл бұрын
Thank you!
@calmpuffin
@calmpuffin 3 жыл бұрын
THANK YOU
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
I found my Selenium script taking 45 seconds to load instead of 4-5. I’m assuming it’s some weird circular import but it was working fine the day before. Totally stumped.
@yardez5990
@yardez5990 3 жыл бұрын
thank you for your lessons)
@MrPatak007
@MrPatak007 3 жыл бұрын
But shouldn't you avoid circular dependencies in the first place? If some components of your code are circularly dependent it creates difficult to read spaghetti code and makes adding functionality an exponentially larger process the more code you have.
@mCoding
@mCoding 3 жыл бұрын
Yes, you should avoid circular dependencies in the first place if you can. Unfortunately in larger projects with many contributors this is harder than it sounds. Furthermore, as i showed in the video, it is possible to end up with a circular import without having a circular dependency due to type hinting.
@astropgn
@astropgn 2 жыл бұрын
In practical use, how can A ever be created if it needs B and B needs A?
@AntonioAndrade
@AntonioAndrade 3 жыл бұрын
Thanks 😊
@friedkeenan
@friedkeenan 3 жыл бұрын
is the audio slightly desynced for anyone else?
@mCoding
@mCoding 3 жыл бұрын
Yep, new camera setup and I didn't notice until it was too late.
@Desslosh
@Desslosh 3 жыл бұрын
So THAT's what the __init__ files are for!
@amidfallen
@amidfallen 2 жыл бұрын
Since you have mentioned packages, what about making video about them? :)
@mCoding
@mCoding 2 жыл бұрын
I say a fair bit about packaging in my automated testing video, you might want to check that out!
@reefhound9902
@reefhound9902 10 ай бұрын
I really only encounter this in library modules, such as a module of stringLibrary functions that might need something in listLibrary, then something in listLibrary that might need something in stringLibrary. One big library would solve the imports but the whole nonsense could easily be handled by Python. Simply keep track of what has been imported and if something has already been imported then ignore that import.
@mCoding
@mCoding 10 ай бұрын
It can definitely be solved in a few different ways, but it's slightly more subtle of a problem because Python *does* already keep track of if something has been imported and ignore it if it has already been imported.
@reefhound9902
@reefhound9902 10 ай бұрын
@@mCodingif it did then why is there a "circular reference"?
@falxie_
@falxie_ 3 жыл бұрын
I've noticed this a lot in the JavaScript world
@huzzah3234
@huzzah3234 Жыл бұрын
Someone please help me, my brain is pure mush. I am looking over and over at the interface package example, and I'm not saying it doesn't work, but I simply cannot comprehend why it works. How is the interface package any different from just the regular package? Main -> B -> IB -> C -> IA -> A -> B just seems the same to me. ---------------- Edit ---------------- (I am sure I myself will be looking for this comment many times in the future...) I was sort of right. If you do the interface package thing, and then in B.py you try to "from ..a import C" and in A.py you try to "from ..b import B", you will fail all the same. This is what was wracking my brain because I thought this was just supposed to work, but no, it doesn't and it's not supposed to. What the interface package model provides is the ability for all those subpackages to refer to each other without their actual package's initialization code, which can then be transferred to the interface package. So, inside the package, just refer to them through the packages themselves (like, in B.py: "from .._a.A import A"), not the interface. Outside the package, refer to them via the interface.
@huzzah3234
@huzzah3234 Жыл бұрын
Update - I found my own comment now that I got confused again. Thank you past me!
@misaalanshori
@misaalanshori 3 жыл бұрын
I never thought this would be a problem lol
@dr.mohamedaitnouh4501
@dr.mohamedaitnouh4501 Жыл бұрын
I have constantly this issue and your video shed some light but does not resolve the problem. I am still struggling to remove it. I am wondering why they say Python is easy. Python's inventor could remove this stupid circular import that is giving pain for beginners.
@gregorymorse8423
@gregorymorse8423 3 жыл бұрын
If your module has code in it not just definitions, then many of these solutions would not work. It's the last case in the video though, as he said it's a disaster case
@AveN7ers
@AveN7ers 3 жыл бұрын
Heh I experienced this circular import problem this week, only in TypeScript not python. It confused the hell out of me.
@arinzeaguolu1341
@arinzeaguolu1341 3 жыл бұрын
Had this issue in a flask app I was working on had to use call-time
@nightfox6738
@nightfox6738 3 жыл бұрын
python needs include guards or pragma once like c...
@freesoftwareextremist8119
@freesoftwareextremist8119 2 жыл бұрын
I love watching these videos and then laugh about how stupid python is!
@Cucuska2
@Cucuska2 3 жыл бұрын
There is a slight lag between your voice and the video I think.
@mCoding
@mCoding 3 жыл бұрын
Switched cameras and didn't notice this. Thans for pointing this out!
@tezz-io
@tezz-io 3 жыл бұрын
Header guards
@Cassiusisback
@Cassiusisback 2 жыл бұрын
#pragma once :)
@mCoding
@mCoding 2 жыл бұрын
Python actually implements pragma once via sys.modules, which prevents you from importing the same module twice (unless you delete it)! The issue is because python imports happen at runtime whereas C/C++ imports/includes happen at compile time.
@ej3281
@ej3281 3 жыл бұрын
Importing code from within a method seems like a code smell
@ej3281
@ej3281 3 жыл бұрын
If you're missing a library you should get to know before you use the method that needs it IMO
@mCoding
@mCoding 3 жыл бұрын
If you would like an error for a missing library at runtime, then you should use the option #2 of just using raw imports instead of from imports. However, the purpose of this video was to help you avoid import cycles in your own projects, so it is very likely that all modules that are part of any cycle are all modules within your own code, so there is no chance of them being missing. If you manage to get an import cycle between someone elses code and your code, that's a whole new kind of monster 👻
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
No it’s a good solution. Take my use case for instance where I need to import tensorflow to run a predictive model in just one of my functions that may or may not be called. It saves 2-3 seconds everytime I need to start the program.
@sambit98
@sambit98 2 жыл бұрын
This is
@26-dimesional_Cube
@26-dimesional_Cube 3 жыл бұрын
A hacker give this code to you def password(str_input, str_key): -> int Password_num = 0 str_key_len=len(str_key) str_input_len=len(str_input) for i in range(str_input_len): Password_num += str_key.index(str_input[i])*str_key_len**(str_input_len-i-1) return Password_num This function can take a string and output the password needed to protect the string Puzzle: Make a inverted function where argument are password and str_key Input: Line 1: password Line 2: str_key Output: A string Constrains: str_key cannot have duplicate letter and must have at least character within the str_input
@drygordspellweaver8761
@drygordspellweaver8761 2 жыл бұрын
Bruh this is Python. You don’t need to do “for I in range(len(string))” Just “for letter in string” works. Strings are iterable.
@CAMOBAP795
@CAMOBAP795 3 жыл бұрын
Thanks for the video timing is perfect! But to be honest, all solutions looks ugly, I really dislike python because of these import issues
@luizzeroxis
@luizzeroxis 3 жыл бұрын
Yeah, but what alternative is there? Python has the best import system I know, so I'm not sure many of these problems can even be ever resolved.
@gubigm
@gubigm 3 жыл бұрын
So the solution is that there is no solution...
@markcuello5
@markcuello5 2 жыл бұрын
HELP
@零云-u7e
@零云-u7e 2 жыл бұрын
Also known as a cluster @__&##@#!!!! How do you even get your code so janky? You cannot dynamically unload libraries so consider how bad performance is with in-code loading. In my mind, future importing presumes a class that may rarely be used, depending upon end-user behavior or more importantly, plugin architecture. What happens when C++ code performance tweakers mess up OOP object lifetime concepts in Python.
@lunarmagpie4305
@lunarmagpie4305 3 жыл бұрын
Discord gang
@mCoding
@mCoding 3 жыл бұрын
Hello!
@КирилоХацько
@КирилоХацько 2 жыл бұрын
AWFUL! Python developers MUST work some time in "enterprise" language. Or at least in web stack. DI come long way from theory pattern to a tool with dosens of features
@marcus_17
@marcus_17 3 жыл бұрын
The fact that this is even a problem, IMHO shows that Python isn't designed for software with 100+ lines of code.
@mCoding
@mCoding 3 жыл бұрын
I don't see how these are related, this is not a language specific issue. C has the same problem with function definitions. If f uses g and g uses f (e.g. in mutual recursion), you're in trouble because whichever one you try to define first needs the other, which isn't defined yet. C solves this problem by adding in function declarations without implementations, which is effectively the same solution as the first one presented here for Python, which basically comes down to "it will be there when it's actually needed, don't worry about it now." Most languages share a lot of the same problems and have similar solutions to those problems when you really look into it.
@AnimeGIFfy
@AnimeGIFfy 2 жыл бұрын
worst part of python right here. like holy sh1t
@SkyyySi
@SkyyySi Жыл бұрын
Only that this was dressed with PEP 690...
@glorytoarstotzka330
@glorytoarstotzka330 3 жыл бұрын
little suggestions, instead of calling them "func_a" and "func_b" I think it would be easier to follow along if they were called literally "first" and "second", at least for me
7 Python Code Smells to AVOID at All Costs
22:10
ArjanCodes
Рет қаралды 376 М.
Async for loops in Python
16:36
mCoding
Рет қаралды 67 М.
She made herself an ear of corn from his marmalade candies🌽🌽🌽
00:38
Valja & Maxim Family
Рет қаралды 18 МЛН
It’s all not real
00:15
V.A. show / Магика
Рет қаралды 20 МЛН
super/MRO, Python's most misunderstood feature.
21:07
mCoding
Рет қаралды 221 М.
Positional-only and keyword-only arguments in Python
9:48
mCoding
Рет қаралды 85 М.
Python Generators
15:32
mCoding
Рет қаралды 143 М.
Real 10x Programmers Are SLOW To Write Code
14:51
Thriving Technologist
Рет қаралды 68 М.
The Only Unbreakable Law
53:25
Molly Rocket
Рет қаралды 342 М.
Modern Python logging
21:32
mCoding
Рет қаралды 209 М.
The Absolute Best Intro to Monads For Software Engineers
15:12
Studying With Alex
Рет қаралды 675 М.
Dependency Injection, The Best Pattern
13:16
CodeAesthetic
Рет қаралды 900 М.
Generics are VITAL in typed Python
16:54
Carberra
Рет қаралды 11 М.