0

The question of what the directory structure of a Python project has been asked a number of times on Stack Overflow (e.g. here, here and here)

And many answers are given. But one thing that doesn't seem to be clear in any of those answers is why some projects have repetitive directories. For example, in this article which is often cited, the suggested layout is:

<root>/
|-- Twisted/    
|   |-- __init__.py
|   |-- README
|   |-- setup.py
|   |-- twisted/ 
|   |   |-- __init__.py
|   |   |-- main.py
|   |   |-- test/   
|   |   |   |-- __init__.py
|   |   |   |-- test_main.py
|   |   |   |-- test_other.py
|   |   |-- bin/
|   |   |   |-- myprogram

In this example, /Twisted/twisted/main.py is the main file

But then on the other hand you have advice like this:

Many developers are structuring their repositories poorly due to the new bundled application templates.

<root>/
|-- samplesite/
|   |-- manage.py  
|   |-- samplesite/
|   |   |-- settings.py
|   |   |-- wsgi.py   
|   |   |-- sampleapp/
|   |   |-- models.py

Dont do this.

Repetitive paths are confusing for both your tools and your developers. Unnecessary nesting doesnt help anybody. Let's do it properly:

<root>/
|-- manage.py  
|-- samplesite/
|   |-- settings.py
|   |-- wsgi.py   
|   |-- sampleapp/
|   |-- models.py

My question is not necessarily "which way is better?", since there may be pros or cons to each way.

Instead, my question is, if I go with the more simplified second style, what will I lose? Is there a good reason to have a /<root>/Twisted/twisted/main.py directory structure rather than just /<root>/twisted/main.py ? Does it make it easier somehow to share my application or make the import process smoother? Something else?

Community
  • 1
  • 1
David White
  • 1,763
  • 2
  • 16
  • 27

2 Answers2

2

I believe the most common layout of python projects is something like this:

project/
|-- setup.py
|-- bin/
|-- docs/ ...
|-- examples/ ...
|-- package/
    |-- __init__.py
    |-- module1.py
    |-- module2.py
    |-- subpackage/ ...
    |-- tests/ ...

Where the project is the name of the project and the package is the name of the top level import, for example scikits-learn and sklearn. The package has everything that python should be able to import, and you import using the package name. For example from package import thing or from package.module1 import thing. The project has the package and any supporting things like docs, examples and installation scripts. Notice that there is typically no __init__.py in project because project is not python importable. It is common for the project and package to have the same name, but not required.

Bi Rico
  • 25,283
  • 3
  • 52
  • 75
0

Those two documents are closer than you think. Both Interesting Things, Largely Python and Twisted Related (your first example) and the django-admin startproject docs assume you are outside of the project repository while Structuring Your Project (your second example) assumes you are inside the repository. To quote, "Well, they go to their bare and fresh repository and run the following...".

The django docs state that if you run

django-admin.py start-project samplesite 

both the project directory and project package will be named and the project directory will be created in the current working directory

The command creates the project directory for you, so you certainly shouldn't be inside of an already-created project directory when you run it. The docs go on to say

django-admin startproject myproject /Users/jezdez/Code/myproject_repo 

If the optional destination is provided, Django will use that existing directory as the project directory

Now, suppose you were already in /Users/jezdez/Code/myproject_repo. Then you would do

django-admin startproject myproject .

to create the project package in the current directory. Voila, you've got the second author's example! The author was really just telling you to avoid the first form if you are creating your repo before running the command.

So, lets redraw your directory structure. In the first example, <root> is the directory where you hold your dev repos. Twisted is the directory with your repo. (As an aside, that directory shouldn't have an __init__.py because its not a package directory). In the final example, <root> is the repo directory itself. Supposing I named that directory DjangoExample, then the structure would be

<root>
|-- Twisted/    
|   |-- __init__.py
|   |-- README
|   |-- setup.py
|   |-- twisted/ 
|   |   |-- __init__.py
|   |   |-- main.py
|   |   |-- test/   
|   |   |   |-- __init__.py
|   |   |   |-- test_main.py
|   |   |   |-- test_other.py
|   |   |-- bin/
|   |   |   |-- myprogram
|
|-- DjangoExample/
|   |-- manage.py  
|   |-- samplesite/
|   |   |-- settings.py
|   |   |-- wsgi.py   
|   |   |-- sampleapp/
|   |   |-- models.py

As for other differences, the django app has to follow the django framework rules whereas twised follows the more generic python package rules.

tdelaney
  • 73,364
  • 6
  • 83
  • 116