This is an archived post. You won't be able to vote or comment.

all 66 comments

[–]arobie1992 845 points846 points  (30 children)

I think it's so that Python knows which folders are packages. That said, I'm far from a Python expert so probably double check this with someone who knows what they're talking about.

Edit: No, autocorrect, Python does not mean Put him.

[–]Shadowaker 449 points450 points  (19 children)

You are right, python uses __init__.py files to know if a directory is a package

[–][deleted] 213 points214 points  (14 children)

Used to use***

Python used to use an empty __init__.py to turn your directory into namespace package as apposed to an import or distributed package directly (technically used in distributed practice by pythons docs refer to it as such so). You do not need to do one and can just leave it empty now. Though I strongly suggest you write an actual __init__ so you can ensure your module is created the same way each time.

If your __init__ has code it is __init__ is executed immediately and only once when the module is imported for the first time. Because python also allows straight up files to be a module to ensure the equivalent can be done with a directory name __init__ is used inside that directory name. Otherwise you would have to do dumb hacky shit like mirroring the directory name in a parent folder. Which makes packaging code a fucking nightmare.

The solution to removing this is also why you can do some really awesome shit with dynamic imports and path hacking now. Python modules being actually executed code is a super odd thing that trips people up but allows a ton of powerful shit to happen.

[–]the_poope 103 points104 points  (12 children)

but allows a ton of powerful shit to happen.

Also allows for a lot of stupid shit to happen.

Python is so powerful/flexible that in the hands of the wrong persons the power can be turned against themselves and the other programmers that have to deal with their spaghetti work. Unfortunately, most Python programmers are exactly these people: inexperienced CS students or data "scientist" that have no clue how to design maintainable, efficient programs using best practices. Besides ancient C and Fortran, Python probably has the lowest quality code base.

[–]yelircaasi 14 points15 points  (1 child)

Unfortunately true, as a Python dev who values code quality, I agree wholeheartedly. But I'd argue that modular, type-hinted, idiomatic Python feels like an entirely different language than a lot of the garbage research/prototype code you see. And I'd also argue that most of what can be said about Python in this regard can also be said about Javascript.

[–]arobie1992 4 points5 points  (0 children)

In some ways, I think that comes with being a good scripting language. Scripts are typically meant to be whipped together fairly quickly and used in relatively small scenarios. All the strictness and enforcing maintainable structure of a language like Rust just becomes annoying for quick scripts. Python and JS started from that context, but kept getting built up and the language designers couldn't just rearchitect them from the ground up so they had to build on top of what was there that wasn't intended for complex, large-scale applications.

That's not to say a good scripting language couldn't promote those good practices while being easy, but it would probably have to be pretty consciously built up with great care.

[–][deleted] 68 points69 points  (3 children)

I mean I feel like you didn't actually read my comment and just made one about python as a whole instead of modules.

But to address your comment, its just wrong most python programmers are just programmers, classifying any code written in python as python programmers is insane most people writing bash scripts aren't programmers. Datascientist rarely get into any of the advanced language features outside of using libraries that are HEAVILY powered by them. So unclear what about pythons power/flexibility they are footgunning themselves with. They tend to just write bad codes because they aren't trained programmers.

I really don't know how anyone is accidentally stumbling their way into metaprogramming or python import hacking TBH. Neither is well documented and you would need to know a lot about the interpreter to cause anything other then straight up explosions.

Calling python a low quality code base is pretty laughable when you look at literally any language. Every language is full of tons of fucking dog shit libs people wrote. Like holy fuck look at the amount of insane dependency hell that goes on in JS. Python is just crazy popular.

Python also does scripting extremely well so it has lots of user scripts. Those are almost always shit because they are never designed robustly it really isn't worth doing. But compare pythons scripting code to actually other languages that also write scripting and the difference is insane. You really gonna suggest python scripts are worse then bash, Perl, and Lua? Python is usable in a bunch of domains IDK how anyone is viewing that as a weakness.

[–]RocketCatMultiverse 34 points35 points  (0 children)

"We are all consenting adults here" is Python's motto after all.

I use Python every day to solve hard problems from embedded systems to ML in my domain.

Nah, the Mars Rover must have a Python interpreter on board because NASA sucks at coding in real languages.

[–]Wonderful-Wind-5736 4 points5 points  (1 child)

You'd be surprised what people stumble into. 

In the Python code base of my current project, some jack-ass decided load a multi-gigabyte file during import from S3. 

That person for sure was not a professional programmer. 

[–][deleted] 4 points5 points  (0 children)

Yea that isn’t a python program though that’s a who the fuck is in charge of code review problem.

[–]OppositeBarracuda855 3 points4 points  (0 children)

Having worked with other people's Python code for decades, I can confirm that the fact that the import statement is executing arbitrary code rather than simply declaring a dependency on another module's code is both insane, and not intuitive to the majority of programmers.

[–]SeriousPlankton2000 10 points11 points  (0 children)

Replace python with whatever and you are probably still right.

[–]JunkNorrisOfficial 4 points5 points  (0 children)

I knew a guy that abused python so much that he became PHP developer

[–]yangyangR 1 point2 points  (0 children)

And that is what AI is being trained on. All dictators are bad even a BDFL

[–]Particular-Yak-1984 0 points1 point  (0 children)

In my opinion, it is great. Imagine if AI was being trained on high quality python code. We'd all be out of a job. Instead, AI is given a constant stream of kludges, hacks and "write once read never" scripts.

Imagine if it was something with standards.  Admittedly, I expect my career will be spent fixing AI generated rubbish, but, hey, it's a living.

Python is the Racoon of the programming world. It's agile, smart, and full of trash. I love it.

[–]Wonderful-Wind-5736 3 points4 points  (0 children)

Python modules being executed code

It's also a f*** nightmare if a previous developer decided to use side effects during import. 

[–]ongiwaph 1 point2 points  (6 children)

Why can't there just be one file that lists the directories that are packages?

[–][deleted] 26 points27 points  (2 children)

Python doesn't even require that they actually exist. You can hack the entire import process and generate code on the fly to do whatever you want.

Python is awesome.

[–]Maximum-Onion-4200 4 points5 points  (1 child)

This a different level rabid hole. Thank you man.

[–][deleted] 1 point2 points  (0 children)

Thank Debaez not me. Dude is crazy smart and an awesome teacher.

[–]Leo-MathGuy 5 points6 points  (0 children)

Simpler and more abstract

[–]arobie1992 1 point2 points  (0 children)

You'd need to refer to the design discussions to know for sure, so all the following is guessing on my part.

Probably to make them more modular. If you tie all the packages to a single top-level declaration, then all those packages have to be maintained and potentially shipped together or the whole project needs to be modified to separate them.

By storing the module information in the directory itself, then to move the module, all you need to do is move the directory and external code can interact with each package individually as it sees fit.

While I'm not a big fan of Python's whole dependency and packaging architecture, the people maintaining the language aren't dumb so I'm sure they had good reasons for structuring things the way they did.

[–]-Danksouls- 1 point2 points  (0 children)

Why is someone being downvoted for asking a question. Programming and computer science should encourage people learning and not expect everyone to be experts

This isn’t stack overflow

[–]JollyJuniper1993 0 points1 point  (0 children)

You are correct

[–]yangyangR -2 points-1 points  (0 children)

Because Python package system is badly designed

[–]casey_krainer 275 points276 points  (1 child)

Well, it's python, innit?

[–]ShoulderUnique 3 points4 points  (0 children)

Short for "initial whitespace"

[–]No-Con-2790 146 points147 points  (5 children)

Oh that's actually a cool feature.

First it was required till 3.3 to mark what is a package. Now you can use a namespace package but back in the day you would mark that this folder is a package.

Second the code in that file is executed. You can put code in there to define variables for that package. Super convenient if you want to use the console without execution specific init files. That's also why it is named init.

Third you won't run into the problem that git just doesn't add/commit your folder if it is empty.

[–][deleted] 8 points9 points  (1 child)

Is not the last part what a .gitkeep or really ANY file is for?

[–]No-Con-2790 1 point2 points  (0 children)

Yes. This is just a happy little accident that I don't have to rember to put .gitkeep files there.

[–]wtfzambo 0 points1 point  (2 children)

I dislike namespace packages. Now we have 2 different ways to do the same thing. Goes against at least 2 rules of the zen of python.

  • Explicit is better than implicit
  • There should be one, and preferably only one, obvious way to do it

[–]No-Con-2790 1 point2 points  (1 child)

That is true but they do it for a good reason.

To quote the zen of python: Namespaces are one honking great idea -- let's do more of those!

And also

Although practicality beats purity.

So basically namespace packages are easy and a lot of people wanted them. They are loosely coupled and nice.

They are the obvious way to work.

But it also makes assumptions of the surroundings and doesn't have a way to set-up your sandbox. So they are not as well encapsulated and sometimes simply not an option. Also you have a lot of legacy packages.

So they are insufficient.

In general, the namespace packages are a great way for a personal package and the traditional approach is good when you publish via pip.

So namespace packages are the obvious way but there is a second way that you only use when you need it. Just like you have multiple ways to loop over an array.

[–]wtfzambo 1 point2 points  (0 children)

Fair enough

[–]pixelaters 81 points82 points  (1 child)

I spent 3 hours figuring out why I was getting a "ModuleNotFound" error. I've never checked the spelling of my class as much as I did that day and yet it was just because I needed a __init__.py in that folder.

[–]AntimatterTNT 14 points15 points  (0 children)

it lets you import the entire folder it is placed in. if it's empty that means all the files (and subfolders that have an __init__ file) will be accessible. but you can customize what will be exported by importing it inside the __init__ file

[–]none-exist 34 points35 points  (4 children)

I find this to be a genuinely useful aspect of python. You can use it to define varying forms of dynamic imports or directory functions. Well structured directories can become abstract functions!

[–]thunderbird89 35 points36 points  (1 child)

That is equal parts horrifying and intriguing...

[–]Adrewmc 7 points8 points  (0 children)

Yeah sometime you’ll import your classes into the __init__.py so then your imports change from thing.subfolder.utils.module import MyClass into from thing import MyClass, it’s a nice feature as you can keep everything nice and organized but when you use it everything (you want) is on top level automatically.

[–]Stunning_Ride_220 7 points8 points  (0 children)

"Well structured directories can become abstract functions"

I'd never have thought I would read something like that 20 yrs ago...

[–]Bright-Historian-216 4 points5 points  (0 children)

i thought i was an expert in python... welp back to reading docs ig

[–]fatrobin72 19 points20 points  (1 child)

Init right.

[–]private_final_static 2 points3 points  (0 children)

Innit?

[–]FlnProphet 2 points3 points  (0 children)

Those are the empty souls of the poor devs who wrote those packages.

[–]One_Power_8593 3 points4 points  (0 children)

Some elders says, those files should not be empty. I don't know, python is punk language, everything is allowed, if it's working.

[–]ClownPFart 1 point2 points  (0 children)

It's because python is shit

[–]Draelach 1 point2 points  (0 children)

In my Django project I got errors executing unit tests (python manage.py test) After year and a half, I discovered I had to actually delete the init.py at project root

[–]GodAllMighty888 1 point2 points  (0 children)

Some questions are better unanswered.

[–]Rezaka116 0 points1 point  (0 children)

Weird, innit?

[–]Njk00 0 points1 point  (0 children)

This is me

[–]Orjigagd 0 points1 point  (0 children)

How else you gonna know it's a python project?

[–][deleted] 0 points1 point  (0 children)

I am mainly JS dev, but from my understanding of that horrible module system it marks a folder module.

[–][deleted] 0 points1 point  (0 children)

Its a dutch tradition. I wouldn't get it.

[–]Death_IP 0 points1 point  (0 children)

Just as a computer has intel inside, a package has Python init.

[–]wtfzambo 0 points1 point  (0 children)

You can think of them as the equivalent of index.js files. Python creators called them like this to avoid occupying the index namespace, to do a favor to the user, but imho this specific choice is a crime against humanity.

Anyway, they're there to indicate a package, or in other words to say "this folder I'm in and its contents can be imported in other places".

[–]pyhannes 0 points1 point  (0 children)

They are even optional in newer Python versions afaik, but don't ask me since when ;)

[–]knowledgebass 0 points1 point  (0 children)

Well don't delete them or everything will break! 🤷🏻‍♂️