Python HOW TO structure a Beginner OR Advanced Projects ?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone i hope all of you are doing well and in this video i'm going to talk about how you should organize your python files within the project that you work on now i got a lot of comments lately of people asking me how they should manage their code in a python project so i feel like a video where i show you how i structure my python files and giving you some examples along the way could be something very useful for you so let's get started [Music] now before we actually start giving some examples i want to say that there is no standard rule of how a python project should look like it is really up to you where you want to locate your classes your functions your variables and your if statements and your for loops so by the end of this video you can take a look in the description because i'm going to provide there some useful links from different people that have already created some templates and also some important information that i have found in the python official documentation okay so i'm already inside some random directory and i already came up with two templates that i want to show you throughout this video so one of them will be inside the folder that i named it structure one like that now one of the examples is going to be for more basic python projects and the other one is going to be probably for some cases where you want to create more complex and more advanced python projects okay so if i clean the screen here for a minute and then go with tree then you can see that it shows us the structure of this directory in a nicer way okay so you can see that inside here i have three files and the first one will be run dot py and this file is mainly going to be saved for triggering minimal functions and maybe you could add some sentence or two about what this file is responsible for and this file is really going to be minimalistic so i imagine this file only triggering one or two functions but the really rest of the code and the rest of the actions that you want to take is going to be within helpers.py so the helpers.py could be a file where you put in all the functions that you want to write and then this run.py is going to import each function from the helpers.py now you could also name the helpers.py something like functions.py or actions.py but something like that but you mainly want to keep one file for triggering everything that you want to trigger and as well as one more file for all of your functions now you can already pay attention for the consonants dot py as well now if you come from another programming language basically a constant means a variable that is not going to change throughout the execution of your program so what that means it means that for example if you want to calculate all the prime numbers in a range of numbers from 1 to 100 then you probably want to store inside a constant dot py two variables like start range and end range so it is very important to understand that inside the constants there are always going to be variables that are not going to change throughout the execution of the program and you are not going to override their values now to really show you a basic project within this structure i really want to develop a project where i calculate all the prime numbers between some given range of numbers so let's go ahead and see an example of that in pycharm okay so as you can see i'm already inside this folder and i have already opened the run.py and as well as the other files now as i said in the run.py the code is going to be very minimalistic and usually i go with that approach as well so we could say here triggering the entire project do this by python run dot py okay so it is important to do something like that and later on we are going to use some import statements so it is a greater idea to move these comments out maybe one or three lines after that okay so now we can basically go with something like def run so we are creating a function of the lines that we want to execute and in here we probably want to execute a function that we are going to name it later something like calculate primes something like that and we can already assume that this is going to receive a range of numbers so we could say start equals to maybe 1 and finish equals to 100 now you can already pay attention that we have some good candidates to store constants because as you can see those variables are never going to change throughout the execution of the program so maybe you would want to go and store some constants inside your constant dot py and that will be by basically going to your constants dot py and say something like start equals to 1 and finish equals to 100 now actually there is a great reason that i capitalize each letter here because it gives a cleaner look to our eyes when you want to see the reference to that variable and as well as in most of the programming languages if you have constants that are stored in most of the cases you are going to see their name with all uppercase letters okay so this is why i decided to go with that and now i can go back to my run.py and basically besides using those numbers hardcoded in here i can go with something like the following so i could say in the first line import constants as const something like that or as c whatever you want and we could say here c dot start and in here c dot finish and so it really gives a cleaner look when you look in that way okay so i know that we did not create anything about calculate primes yet so we will create that in a second and maybe we would like to store their results as a variable that we could name primes and maybe we would want to print the results of that so we could say print primes okay so once you have this scenario then it is a great idea to actually call this run function now the way that you want to call this function is by wrapping this in a conditional that says if thunder name equals to thunder main like that and that will be double equal sign okay so if you never saw me writing this conditional in here then i have a video on that that is quite explaining what is the purposes of writing this conditional but basically this has happened to be a convention line of code in python that checks if this file has run directly or has been imported and we only want to execute this run function if we execute this directly by saying python run dot py so this is why i wrapped the call of this function within this condition okay so now we could go to helpers.py and really start creating some functions that will help us to calculate the prime numbers in a given range of numbers so we could open our helpers.py and we could also comment here something like functions that are going to help calculate prime numbers and we did not comment anything in constant py as well so we could say here useful variables that are going to be used okay so something like that could be fine okay so inside the helpers.py we are going to write our functions now i really like to go with a function that first returns if the number is prime or not and then later on we can write some other function that is probably going to calculate all the prime numbers in a given range of numbers okay so we called first start with a function that says def is underscore prime like that and for sure this is going to receive the num as a parameter so we want to receive one parameter at least and now here we want to return true or false if the given number is prime number or not now since in that video i'd really like to focus on the project structure itself and not on writing some algorithms for stuff like that i'm going to paste the code snippet that is really responsible to return if the number is prime or not and let me paste this in in here and i explain what is going on on here now first of first i check if the given number is greater than one because i want to eliminate all the scenarios that the numbers are less than one meaning one so this is why i went with this if conditional in here and later on i check in the range of numbers between two to the given number if the remainder of such a division is not equal to zero now if this would be actually equal to zero then this already proves us that this number is not a prime number so this is why i said here in the comment section if the remainder is not equal to zero then keep on checking and i wrote discontinue in here and if we hit the else conditional in here then it already means that we can return false because if this division remainder is actually zero then it means that it is not a prime number and then later on once we finish with this all for loop then we can return true because if the function never returns false then it means that all the checks of the division has been completed successfully and then we can allow ourselves to return through by the end of this function now to actually verify ourselves in here for a second we could basically print and call the is prime and then we could try to test this with a number like 34 and obviously this is not a prime number and then we could also test this with a number like 53 that i already know that this is a prime number so now we called run the helpers.py file and you can see that the first result is false and then the second one is true so this means that the function is actually working great okay so now we can continue on writing a function that is probably going to say something like def calculate primes like that and as i said in the beginning of this example i'm going to receive here start and finish so we will know the range of the numbers that we should check okay so inside here we could open a new list and we could say primes equals to an empty list and we could start an iteration like the following so for n in range and we could start and finish like that so this will be an iteration throughout all the integers between 1 to 100 in the future and then we could say if is prime and like that then we could append this to our list like that so primes dot append n and then we could return primes like that okay so once we have completed this then it is a great idea to go back to our run.py and see how we can import each function from the helpers.py so we could basically say import helpers like that now the reason that i can do this it is because the run dot py and the helpers dot py are in the same directory so it is very okay to go with this approach okay so now as you can see we still got this error in here because we probably want to say helpers dot like that and then the error will be fixed now you could also use the wildcard import in here so if i press undo for a minute and go and change this line to something like from helpers import everything like that then you can see that the error is disappearing as well because now you don't really have to refer to the file's name and that is perfect now if i run this program so i will say run dot py and then you can see that we receive a list of all the numbers that are prime numbers now here's the real deal where the constants dot py could be actually very useful now let's say that you want to play around with this program a little bit and you want to skip all the numbers between 20 to 50 and you probably look for a way where you should implement the logic of that okay so basically it means that in helpers.py we should go to our calculate primes and we probably want to write here some more conditional that is going to be responsible to skip the numbers that are between 20 to 50. so to do this we could basically add one more constant in our constants.py and we could say here skip underscore range and that will be equal to range of numbers between 20 to 50 like that and then we could go to our helpers dot p y and right here some more conditional that is going to say and and here we want to check if the iterated number is between 20 to 50 so we could go up here and we could import this from the constants so we could say in here import constants as c like we did with the run dot py and then i will go back to our conditional and we could say and n not inside the c dot skip range okay so you'll see whenever you want to implement some logic and you want to create some variable for it and this is not going to change throughout the execution of the program then it is a perfect idea to put all this information inside the file that you can name it variables constants or something that you can really understand in the future that this file includes all the information about storing some variables and once i have added this functionality inside this if statement then if i go ahead inside our run.py and really execute dot py then you can see that the program has been changed and after 19 we directly see 53 and we don't see 21 or something that is really a prime number in the range of the skip range so this could be one example how you want to divide your project you could basically store all your information in a one file and your functions in another file and then there will be one more file like py that will trigger and collect everything and will execute the stuff that you want to execute alright so now that we understood the purpose behind each file in such a project now let's assume that we want to take this project one step further and let's assume that we want to send a nice email about the results of an execution of such a program now what this will mean this will mean that we probably will have to go ahead inside our helpers.py and put in some additional functions that will be responsible to send email to someone that we decide but doing such a task is something that is quite complex and we might want to avoid creating those functions inside the already existing helpers.py because if you remember our helpers.py is only including some functions that are dealing with operations around prime numbers so maybe locating email actions inside that file could be something not nice and not organized and in that case we might consider creating a separated folder for all the actions that are going to deal with all the actions that are necessary to send an email so in that case it is a great idea to restructure your project and make it to perform like python packages now python packages will allow you to store your entire functionality inside the directory and then you can import its functionalities and its classes by basically referring to that folder name so let me show you a template of how this project should be structured if we want to add some functionality like sending an email okay so i'm back to the terminal for a minute and in here you could pay attention that i'm located inside a directory that is named structure 2 unlike before where i was located inside structure 1. so if i'm going to hit here the tree then you can see the division of the files and folders in here so you could see that now we got directories email and prime calculation and then outside of everything we have our run dot py now you could also see that in each directories i still have the files that says constants and helpers and as well as in the prime calculations but you could also pay attention that i included a file that is saying dunder in it dot pi now normally when you want to divide your project into python packages you have to create a convention file that its name is double underscore in it and if it doesn't make sense for you right now then i will show an example of that just in a minute because i'm going to restructure our project and make it to support such a template so let's go ahead and see how this could be implemented with the project that we already started to work on okay so to really create the imagination of how this program is going to look like when we restructure it from scratch then i'm going to write in some functions for the actions that i'd like to take in general now i know that those functions are not created yet so we might receive some errors okay so at first we still want to calculate the primes but you probably want to avoid sending an email with only a list of numbers so we probably look for a way to prettify the results that we received maybe we want to display this separated line by line or stuff like that so the next step will be actually to go with something like the following so this could be something like primes dot pretify and i could imagine that this method is going to grab all the numbers and it's going to split each number in a separated line or something like that and once i have done that then we could assign this to a variable for example like prettier and this is going to be equal to that and again everything that i'm doing here is just an imagination and i did not create any of those methods and functions yet so now we could imagine that we import a class that is going to deal with all the functionalities how we should send an email so this could be something like email equals equals to a new instance of an email and now we could override some properties to really customize these emails and those things could be attributes like to body subject and stuff that is dealing with email sending so this could be email dot to equals to let's say john doe at email.com like that and we could say email.subject equals to prime numbers execution between and we could refer to c dot start like that two and then we could call this curly brackets and we could say c dot finish and we should turn this into a formatted string like that and we could say further than that email dot body equals to free tier because if you remember we simulated a method that says prettify that is going to be responsible to really grab the list of prime numbers and turn them to a nicer output okay so at the end this might be something like email.send and this should be enough to really perform all the actions that we want to perform per each execution okay so let's actually go ahead and see how this could be implemented in the new structure that i talked about so first of first i want to show you how you can create a new python package and why we should include the dunder init file in each python project so now i will go and create a new directory inside this project and we could name it email like that and inside this email first we are going to create the dunder init file like the following and as i created that i will allow myself to close this temporarily and i will continue on and i will create here another file that says email like that and in here we are going to include a class that is going to perform some email sending actions and we might also include some helpers file in here although i don't know if we are going to use that much but this is just to make you understand that if you want to add some complex functionalities to the email package that you are including in your project then it is something that is quite possible by maintaining constants for each of your package okay so now that i created those i will close and i will explain why we created the thunder init file now since we created that dunder init file then the python is going to recognize this as a package in the directory of the entire project so this means that you can refer to this email directory like a package that you already worked with so if you already know then you have a lot of packages in python and the basic way that you refer to them is by using import like that now by creating the dunder init file inside the directory you could basically refer to that by only saying import email and this will already recognize it because you have included the dunder init file now if i was to delete the dunder init file from here so i will actually do that then the second that i have done this then i don't have access to the inner files inside this directory but if i was to bring back the file so we will create that again like this and then i will go back to our run dot py then the second that i'm going to hit the dot sign then you can see that there is already an auto completion of the files that are included within this directory so this means that it is being recognized as a package and this is quite critical for us so now we really have access to everything within this directory so we could import every file from here like that and we could also import email.constance and we could import email dot helpers and so on so it is very important to realize that okay so to continue on with our program then i'm going to create a class that we will name it email and i will do that inside the email python file which is under our email directory now i will go ahead and easily say class email and i will type in pass temporarily okay so i'm back inside our run.py and in here we want to import the class that we have just created inside the email.py but before we do this i realize that the variable name in here is quite forbidden because now the python is going to be confused how to refer to the email package because there is a variable that we named email so to avoid such a confusion we could basically use the refactor rename functionality of pycharm and we could rename this variable so we could basically change this to something like new mail like that and this should be good enough to continue from here and now i will go up top here and i will import the email class as a package so this could be by easily saying email dot email import email capitalize and this should be really good and as you can see the error from here is disappeared but now you can realize that there is an error that says us there is no method named send recognized inside the email class and that is perfectly making sense because inside the email class we don't have anything defined so just to avoid such an error we could say here def send and we could only print here something like email has been sent now as you could realize we are not really going to send an email to someone but only i wanted to show you how you can package such a complex functionality and you could already do your comparisons with your own projects how you can package stuff and really maintain more organized code so now that i have done this then if i go back to our run.py then you can see that all the errors have been disappeared okay so now that we understood how we can create a package for a specific area that we want to function then let's go ahead and see how we could do this for calculating the prime numbers in a given range of numbers so to really collect everything that is related to that we could go and create one more directory inside our entire project and we could name it something like prime and then we could move everything that is related to the prime calculation under this directory so we will go and move those like that and we will click on refactor and we could do the same thing for the helpers.py and we will click on refactor as well now the second that i have done this then you could pay attention how the second line in here has changed now you might not have remember this but this was actually used to be like that but since it is moved under the prime directory then it went ahead and actually changed this line for us so this is what the refactor is about and let's actually create the init file in here so python could really understand that this is a package so it will be done there in need under like that and the second that i have done this then i can close this file and i could change this import line to being like an import from a package that we have already done in the email package so we could say import prime dot constants as c like that and you can see now that the line in here that is referring to that c variable is not having any error and you can see that this error is also fine because we have created the under init file so now that we have done this in here then we can close those files and you could see that the primes is still referring to a calculate primes function now it could have been a lot nicer if we would have changed this into a class and then take some different actions within that class by referring to the instance methods so to do this basically i'm going to do the same things that i have done with the email package and i'm going to create one more file just as the same name as the package so i will name a new python file prime like that and i will zoom in a little bit and i will say class prime and inside our constructor we can receive the following parameters so it could be start and finish like that and we could initialize those by saying self.start and as well as self.finish equals to finish like that and now that i have done this then we could create a method that its name would be calculate primes and we could basically copy the exact same function like we have written inside our helpers.py so to really avoid confusions in here i'm going to open the helpers.py and i'm going to split the panes so you could see better okay so in the right pane i'm going to have the dot py that is inside the prime directory and in here i'm going to have the prime file itself so now i will allow myself to copy this from here and paste this in under this method and now we should take some actions to really get rid of those errors and we could change this to self dot start like that and we could change this to self.finish and as you can see we still have some arrows with ease prime so to get rid of this error then we can import everything from the helpers.py so we could say from prime.helpers import everything like that and as i have done this then this error is disappearing from here and now we can remove this entire function in here because we already maintain it inside our prime dot py and for sure we don't want to have duplicated code and i could also delete the prime.constance import in here as i don't really use it in here and we should only leave the is prime in the helpers.py so now i could close this and go back to that file and this file should also import the constants because we are referring to that skip range constant so we could say in here import prime dot constants as c like that and this error should disappear as well and we could jump two lines in here just to follow python conventions and i think that the prime dot pi file is pretty much ready so now that we have done with the customization of that then we can close this out and we can also close the helpers file and you can now guess that the run.py file is going to have some errors because we deleted this function and this file does not understand where the c variable is coming from so to fix that out then i'm going to import the class that we have created like we have done for the email so i'm going to change that to from prime dot prime import prime capitalize because we are only referring to the class that we want to initialize and now that i have done this then we could delete this line and we called say p equals to prime and now to initialize this successfully we have to refer to the constants so we could import the constants like that so we could say import prime dot constants as c like that and as i have done that then i can pass in as the arguments of that instance start equals to c dot start and we could say finish equals to c dot finish and now that i have done this then i could print the calculation of all the prime numbers in the given range of numbers so we could say p dot calculate primes and now that i have done this then you can guess that we want to receive the calculated primes in a lot prettier way because we simulated that by creating the prettify method so i will delete that and now we should imagine something like prettier equals to p dot pre-define like that and now you can guess that this receives an error so we are going to fix that by adding a prettier way to display the prime numbers in a given range of numbers so i'm going to go inside our prime dot pi and i'm going to create here the method which is going to say def prettier and this is going to receive self as an argument as a parameter excuse me and i i'm going to say here something like the following so let's say that we want to split the results into different lines so what that means it means that we want to print a prime number in its own line so we could basically iterate over the results and we could say something like that so i'm going to type in here for result in self dot calculate primes so each time that i'm iterating over the calculate primes method then i probably want to insert it inside a big string that is going to be written with a multiple lines so i can say body equals to nothing like that and then each time i iterate over the results i can fill in the string so we could say something like body plus equals then we could refer to a formatted string and we could say this is a prime number and we could refer to that prime number by saying results and we want to escape the backslash n so that in each iteration we will have a line that is being jumped to the next line and you can do that with the backslash n and now as i have completed this then i can get out of my for loop and i can return that body so we could really have the chance to see the results in a prettier way and now just to show you how this is going to look like let's go back to our run.py and i'm going to they just realized that its name should be prettyfi so excuse me about that and i will go back to here and the error is disappeared okay so just to show you the result of that then i'm going to simply print the prettier so we will say print prettier like that and now we are ready and good to go to execute this program so now if we execute this program let's see the results of that so you can see that we start the iteration over the prime numbers and we see that we have a nice output for each of the prime numbers in the given range of numbers and you can also see that we have the email has been sent line that is arriving from the send method that we have initialized from the email package which is happened to be under the email.pi file and that is perfect because now we have everything at its own place and this is a really basic example of how a python project should look like and this is very important to realize that if you have different functionalities that are quite complex then maybe it is worth to separate those into different packages so later when you go ahead and you want to take only several actions within that specific area then you can already know how to refer to that because it is located inside an organized package all right everyone so let me know how you did with this video because i know that we have covered a lot of information and maybe some of the points are not quite making sense for now but you will see that if you want to develop some large project then packaging stuff within directories and creating this dunder emit file in each directory will going to help you a lot and it will also help you to make your code look a lot nicer and friendly so if you want to come with a larger projects that are going to be successful and also have maintainable code then i will go with the following approach for sure okay so if you like this video please hit the thumbs up button it is very important to me and consider subscribing to my channel if you already did not and i will see you in my future uploads
Info
Channel: JimShapedCoding
Views: 14,488
Rating: 4.9183674 out of 5
Keywords: python automating projects, python projects, python project, python project structure, python writing a project, python beginners project, python advanced project, python, Python
Id: 6OSpm4uXqDw
Channel Id: undefined
Length: 37min 50sec (2270 seconds)
Published: Thu Jan 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.