Wat is de beste projectstructuur voor een Python-toepassing?

Stel je voor dat je een niet-triviale desktoptoepassing (geen web) voor eindgebruikers in Python wilt ontwikkelen. Wat is de beste manier om de mappenhiërarchie van het project te structureren?

Gewenste kenmerken zijn onderhoudsgemak, IDE-vriendelijkheid, geschiktheid voor vertakking/samenvoeging van bronbeheer en eenvoudige generatie van installatiepakketten.

In het bijzonder:

  1. Waar zet je de bron?
  2. Waar plaats je de opstartscripts voor applicaties?
  3. Waar plaats je het IDE-project cruft?
  4. Waar plaats je de eenheids-/acceptatietests?
  5. Waar plaats je niet-Python-gegevens zoals configuratiebestanden?
  6. Waar plaats je niet-Python-bronnen zoals C++ voor pyd/so binaire uitbreidingsmodules?

Antwoord 1, autoriteit 100%

Maakt niet zoveel uit. Wat je ook gelukkig maakt, het zal werken. Er zijn niet veel gekke regels omdat Python-projecten eenvoudig kunnen zijn.

  • /scriptsof /binvoor dat soort dingen in de opdrachtregelinterface
  • /testsvoor uw tests
  • /libvoor uw C-taalbibliotheken
  • /docvoor de meeste documentatie
  • /apidocvoor de door Epydoc gegenereerde API-documenten.

En de directory op het hoogste niveau kan README’s, Config’s en dergelijke bevatten.

De moeilijke keuze is of je wel of niet een /src-boom wilt gebruiken. Python maakt geen onderscheid tussen /src, /liben /binzoals Java of C heeft.

Aangezien een directory op het hoogste niveau /srcdoor sommigen als betekenisloos wordt beschouwd, kan uw directory op het hoogste niveau de architectuur op het hoogste niveau van uw toepassing zijn.

  • /foo
  • /bar
  • /baz

Ik raad aan dit alles te plaatsen onder de map “Naam-van-mijn-product”. Dus, als u een applicatie met de naam schrijven met de naam quux, wordt de map die al deze dingen bevat /quux.

De PYTHONPATH, dan, dan, kan /path/to/quux/foobevatten om de QUUX.foomodule opnieuw te gebruiken.

In mijn geval, omdat ik Komodo Edit gebruik, is mijn IDE Cuftt een enkel .kpf-bestand. Ik heb dat eigenlijk in het hoogste niveau gehouden /quuxDirectory, en laat het toe aan SVN.


2, Autoriteit 62%

Volgens Jean-Paul Calderone’s bestandssysteemstructuur van een Python Project :

Project/
|-- bin/
|   |-- project
|
|-- project/
|   |-- test/
|   |   |-- __init__.py
|   |   |-- test_main.py
|   |   
|   |-- __init__.py
|   |-- main.py
|
|-- setup.py
|-- README

3, Autoriteit 58%

deze blog post van Jean-Paul Calderone wordt gewoonlijk gegeven als een antwoord in #python op freenode.

FileSystem-structuur van een Python-project

DOEN:

  • Noem de map iets dat betrekking heeft op uw project. Als uw project bijvoorbeeld “TWISTED” wordt genoemd, een naam van de map op het hoogste niveau voor zijn bronbestanden Twisted. Wanneer u releases doet, moet u een Versienummer Suffix opnemen: Twisted-2.5.
  • maak een directory Twisted/binaan en plaats je uitvoerbare bestanden daar, als je die hebt. Geef ze geen .pyextensie, zelfs niet als het Python-bronbestanden zijn. Plaats er geen code in, behalve een import van en aanroep naar een hoofdfunctie die ergens anders in uw projecten is gedefinieerd. (Lichte rimpel: aangezien in Windows de interpreter wordt geselecteerd door de bestandsextensie, willen uw Windows-gebruikers eigenlijk de .py-extensie. Dus wanneer u voor Windows inpakt, wilt u deze misschien toevoegen. Helaas is er geen gemakkelijke distutils-truc die Ik weet hoe ik dit proces kan automatiseren. Aangezien op POSIX de .py-extensie slechts een wrat is, terwijl het ontbreken in Windows een echte bug is, als uw gebruikersbestand Windows-gebruikers omvat, wilt u er misschien voor kiezen om alleen de .py extensie overal.)
  • Als je project kan worden uitgedrukt als een enkel Python-bronbestand, plaats het dan in de directory en noem het iets dat gerelateerd is aan je project. Bijvoorbeeld Twisted/twisted.py. Als je meerdere bronbestanden nodig hebt, maak dan in plaats daarvan een pakket (Twisted/twisted/, met een lege Twisted/twisted/__init__.py) en plaats je bronbestanden erin. Bijvoorbeeld Twisted/twisted/internet.py.
  • plaats uw unit-tests in een subpakket van uw pakket (let op – dit betekent dat de enkele Python-bronbestandsoptie hierboven een truc was – u heeft altijdten minste één ander bestand voor uw unit nodig testen). Bijvoorbeeld Twisted/twisted/test/. Maak er natuurlijk een pakket van met Twisted/twisted/test/__init__.py. Plaats tests in bestanden zoals Twisted/twisted/test/test_internet.py.
  • voeg Twisted/READMEen Twisted/setup.pytoe om respectievelijk je software uit te leggen en te installeren, als je je prettig voelt.

Niet doen:

  • zet je bron in een map met de naam srcof lib. Dit maakt het moeilijk om te draaien zonder te installeren.
  • zet je tests buiten je Python-pakket. Dit maakt het moeilijk om de tests uit te voeren tegen een geïnstalleerde versie.
  • maak een pakket dat alleeneen __init__.pyheeft en plaats dan al je code in __init__.py. Maak gewoon een module in plaats van een pakket, het is eenvoudiger.
  • probeer magische hacks te bedenken om Python in staat te stellen je module of pakket te importeren zonder dat de gebruiker de map die het bevat aan zijn importpad moet toevoegen (hetzij via PYTHONPATH of een ander mechanisme). U zult nietalle zaken correct afhandelen en gebruikers zullen boos op u worden als uw software niet werkt in hun omgeving.

Antwoord 4, autoriteit 32%

Bekijk Open een Python-project op de juiste manier sourcen.

Laat me een uittreksel nemen van het projectlay-outdeel van dat uitstekende artikel:

Bij het opzetten van een project is de lay-out (of directorystructuur) belangrijk om goed te krijgen. Een verstandige lay-out betekent dat potentiële bijdragers niet eeuwig op zoek hoeven te gaan naar een stukje code; bestandslocaties zijn intuïtief. Aangezien we te maken hebben met een bestaand project, betekent dit dat u waarschijnlijk wat dingen moet verplaatsen.

Laten we bovenaan beginnen. De meeste projecten hebben een aantal bestanden op het hoogste niveau (zoals setup.py, README.md, requirements.txt, enz.). Er zijn dan drie mappen die elk project zou moeten hebben:

  • Een docs-map met projectdocumentatie
  • Een map met de naam van het project waarin het eigenlijke Python-pakket is opgeslagen
  • Een testmap op een van de twee plaatsen
    • Onder de pakketmap met testcode en bronnen
    • Als een stand-alone directory op het hoogste niveau
      Om een beter idee te krijgen van hoe uw bestanden moeten worden georganiseerd, is hier een vereenvoudigde momentopname van de lay-out voor een van mijn projecten, sandman:
$ pwd
~/code/sandman
$ tree
.
|- LICENSE
|- README.md
|- TODO.md
|- docs
|   |-- conf.py
|   |-- generated
|   |-- index.rst
|   |-- installation.rst
|   |-- modules.rst
|   |-- quickstart.rst
|   |-- sandman.rst
|- requirements.txt
|- sandman
|   |-- __init__.py
|   |-- exception.py
|   |-- model.py
|   |-- sandman.py
|   |-- test
|       |-- models.py
|       |-- test_sandman.py
|- setup.py

Zoals je kunt zien, zijn er enkele bestanden op het hoogste niveau, een docs-map (gegenereerd is een lege map waarin sphinx de gegenereerde documentatie zal plaatsen), een sandman-map en een testmap onder sandman.


Antwoord 5, autoriteit 9%

De “Python Packaging Authority” heeft een voorbeeldproject:

https://github.com/pypa/sampleproject

Het is een voorbeeldproject dat bestaat als hulpmiddel voor de Python Packaging User Guide’s Tutorial on Packaging and Distributing Projects.


6, Autoriteit 4%

In mijn ervaring is het gewoon een kwestie van herhalen. Plaats uw gegevens en code waar u maar wilt. De kans is groot dat je het toch mis hebt. Maar als je eenmaal een beter idee hebt van hoe de dingen precies gaan verlopen, ben je in een veel betere positie om dit soort gissingen te maken.

Wat betreft extensiebronnen, we hebben een codedirectory onder trunk die een directory voor python en een directory voor verschillende andere talen bevat. Persoonlijk ben ik meer geneigd om de volgende keer een extensiecode in zijn eigen repository te plaatsen.

Dat gezegd hebbende, ga ik terug naar mijn oorspronkelijke punt: maak er niet te veel van. Zet het ergens neer dat voor jou lijkt te werken. Als je iets vindt dat niet werkt, kan (en moet) het worden gewijzigd.


Antwoord 7, autoriteit 3%

Niet-python-gegevens kunnen het beste worden gebundeld in uw Python-modules met behulp van de package_data-ondersteuning in setuptools. Een ding dat ik ten zeerste aanbeveel, is het gebruik van naamruimtepakketten om gedeelde naamruimten te maken die meerdere projecten kunnen gebruiken – net zoals de Java-conventie om pakketten in com.yourcompany.yourprojectte plaatsen (en een gedeelde com.yourcompany.utilsnaamruimte).

Hervertakking en samenvoeging, als je een broncontrolesysteem gebruikt dat goed genoeg is, zal het samenvoegingen afhandelen, zelfs door hernoemen; Bazaaris hier bijzonder goed in.

In tegenstelling tot sommige andere antwoorden hier, heb ik een +1 voor het hebben van een srcdirectory op het hoogste niveau (met docen testdirectory’s naast). Specifieke conventies voor documentatiemapstructuren zijn afhankelijk van wat u gebruikt; Sphinxheeft bijvoorbeeld zijn eigen conventies die door de snelstarttool worden ondersteund.

Gebruik alstublieft setuptools en pkg_resources; dit maakt het veel gemakkelijker voor andere projecten om te vertrouwen op specifieke versies van uw code (en voor meerdere versies om tegelijkertijd te worden geïnstalleerd met verschillende niet-codebestanden, als u package_datagebruikt).

Other episodes