Pythonアプリケーションに最適なプロジェクト構造は何ですか?[閉まっている]


730

Pythonで重要なエンドユーザーデスクトップ(ウェブではない)アプリケーションを開発したいとします。プロジェクトのフォルダー階層を構造化する最良の方法は何ですか?

望ましい機能は、メンテナンスの容易さ、IDEとの親和性、ソース管理の分岐/マージへの適合性、およびインストールパッケージの簡単な生成です。

特に:

  1. ソースはどこに置きますか?
  2. アプリケーションの起動スクリプトはどこに配置しますか?
  3. IDEプロジェクトをどこに配置しますか?
  4. ユニット/受け入れテストはどこに置きますか?
  5. 設定ファイルなどのPython以外のデータはどこに配置しますか?
  6. pyd / soバイナリ拡張モジュール用のC ++などの非Pythonソースをどこに置きますか?

回答:


378

あまり問題ではありません。あなたを幸せにするものは何でも働きます。Pythonプロジェクトは単純なものになる可能性があるため、多くの愚かなルールはありません。

  • /scriptsまたは/binその種のコマンドラインインターフェースのもののために
  • /tests あなたのテストのために
  • /lib C言語ライブラリ用
  • /doc ほとんどのドキュメント
  • /apidoc Epydocで生成されたAPIドキュメントの場合。

また、最上位のディレクトリには、README、Config、その他を含めることができます。

難しい選択は、/srcツリーを使用するかどうかです。Pythonはの区別を持っていない/src/libと、/binJavaやCのように持っています。

トップレベルの/srcディレクトリは一部の人にとって無意味と見なされているため、トップレベルのディレクトリはアプリケーションのトップレベルのアーキテクチャになる可能性があります。

  • /foo
  • /bar
  • /baz

これらすべてを「name-of-my-product」ディレクトリの下に置くことをお勧めします。したがって、という名前のアプリケーションを作成している場合、quuxこのすべてのものを含むディレクトリはという名前になり /quuxます。

別のプロジェクトのPYTHONPATHを含める/path/to/quux/fooと、QUUX.fooモジュールを再利用できます。

私の場合、Komodo Editを使用しているので、IDE cuftは単一の.KPFファイルです。実際にはそれを最上位/quuxディレクトリに置き、SVNへの追加は省略します。


23
ディレクトリ構造をエミュレートすることをお勧めするオープンソースのPythonプロジェクトはありますか?
ラン

4
良い例としてDjangoを見てください。
S.Lott、2009年

33
私はDjangoを良い例と見なす傾向はありません。
Charles Duffy

18
re "tricks":Djangoはルートプロジェクトフォルダの親をsys.pathに追加するため、モジュールは「from project.app.module import klass」または「from app.module import klass」としてインポートできます。
ジョナサンハートレー

3
ああ、私はこのトリックが大好きで今使っています。共有モジュールを別のディレクトリに置きたい、システム全体にモジュールをインストールしたくない、または手動でPYTHONPATHを変更するように人々に依頼したくない。人々がより良い何かを提案しない限り、私はこれが実際には最もクリーンな方法だと思います。
Yongwei Wu 2017

242

ジャン=ポール・Calderone者によるPythonプロジェクトのファイルシステムの構造

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

23
Project/project/?ああ、2つ目はパッケージ名です。
Cees Timmerman、2011年

44
binフォルダー内の実行可能ファイルはどのようにプロジェクトモジュールを参照しますか?(Python構文../でincludeステートメントが許可されているとは思いません)
ThorSummoner 14年

8
@ThorSummonerシンプル。あなたはパッケージをインストールします!(pip install -e /path/to/Project
クロルタン2014

22
誰かがこのレイアウトのサンプルをhello.pyとhello-test.pyで圧縮し、newbsで使用できるようにするとすばらしいでしょう。
jeremyjjbrown 2015年

8
@Blokeコアは-eフラグであり、パッケージを編集可能なパッケージとしてインストールします。つまり、実際のプロジェクトフォルダーへのリンクとしてインストールします。これで、実行可能ファイルはimport project、モジュールにアクセスできるようになります。
Kroltan 2016年

232

Jean-Paul Calderoneによるこのブログ投稿は、Freenodeの#pythonの回答として一般的に提供されています。

Pythonプロジェクトのファイルシステム構造

行う:

  • プロジェクトに関連する名前をディレクトリに付けます。たとえば、プロジェクトの名前が「Twisted」の場合、ソースファイルのトップレベルディレクトリに名前を付けますTwisted。リリースするときは、バージョン番号のサフィックスを含める必要がありますTwisted-2.5
  • ディレクトリTwisted/binを作成し、実行ファイルがあればそこに配置します。.pyそれらがPythonソースファイルであっても、拡張子を付けないでください。プロジェクトの他の場所で定義されたメイン関数のインポートと呼び出しを除いて、コードをコードに含めないでください。(わずかなしわ:Windowsでは、インタープリターはファイル拡張子によって選択されるため、Windowsユーザーは実際には.py拡張子を必要とします。そのため、Windows用にパッケージ化するときに、それを追加することができます。残念ながら、簡単なdistutilsトリックはありません私はこのプロセスを自動化することを知っています。POSIXでは.py拡張子が唯一のイボであるので、Windowsでは欠落は実際のバグですが、ユーザーベースにWindowsユーザーが含まれている場合は、.pyどこでも拡張子。)
  • プロジェクトが単一のPythonソースファイルとして表現できる場合は、それをディレクトリに配置し、プロジェクトに関連する名前を付けます。たとえば、Twisted/twisted.py。複数のソースファイルが必要な場合は、代わりに(Twisted/twisted/空のを使用してTwisted/twisted/__init__.py)パッケージを作成し、そこにソースファイルを配置します。たとえば、Twisted/twisted/internet.py
  • 単体テストをパッケージのサブパッケージに入れます(注-これは、上記の単一のPythonソースファイルオプションがトリックだったということを意味します- 単体テストには常に少なくとも1つの他のファイルが必要です)。たとえば、Twisted/twisted/test/。もちろん、でパッケージにしてくださいTwisted/twisted/test/__init__.py。のようなファイルにテストを配置しますTwisted/twisted/test/test_internet.py
  • 気分が良ければ、それぞれソフトウェアを追加Twisted/READMETwisted/setup.pyて説明し、インストールします。

してはいけないこと:

  • srcまたはと呼ばれるディレクトリにソースを置きますlib。これにより、インストールしないと実行が困難になります。
  • テストをPythonパッケージの外に置きます。これにより、インストールされているバージョンに対してテストを実行することが困難になります。
  • そのパッケージの作成だけであり__init__.py、その後にすべてのあなたのコードを配置します__init__.py。パッケージの代わりにモジュールを作るだけで、より簡単になります。
  • ユーザーがそれらを含むディレクトリをインポートパスに(PYTHONPATHまたはその他のメカニズムを介して)追加することなく、Pythonがモジュールまたはパッケージをインポートできるようにする魔法のハックを考え出してください。すべてのケースを正しく処理するわけではなく、ソフトウェアが環境で動作しない場合、ユーザーはあなたに腹を立てます。

25
これはまさに私が必要としたものでした。「Pythonがモジュールまたはパッケージを含むディレクトリをインポートパスに追加しなくても、Pythonがモジュールまたはパッケージをインポートできるようにする魔法のハックを考え出そうとしないでください。」知っておきたい!
ジャック・オコナー

1
ことは、これはそれを配置するプロジェクトの重要なドキュメント部分については触れていません。
lpapp

14
「ソースをsrcまたはlibと呼ばれるディレクトリに置く。これをインストールしないと実行が難しくなります。」について混乱しています。何がインストールされますか?問題の原因となったのはdir名ですか、それともそれがサブディレクトリであるという事実ですか?
Peter Ehrlich、

4
「モジュール自体にテストを分散する必要があると主張する人もいます–そうではありません。多くの場合、ユーザーの複雑さが増します。多くのテストスイートでは、追加の依存関係とランタイムコンテキストが必要になることがよくあります。」python-guide-pt-br.readthedocs.io/en/latest/writing/structure/...
endolith

2
「このため、インストールしないと実行が難しくなります。」-それがポイント
Nick T

123

Pythonプロジェクトを正しい方法でオープンソーシングするをご覧ください。

その優れた記事のプロジェクトレイアウトの一部を抜粋してみましょう。

プロジェクトを設定するときは、レイアウト(またはディレクトリ構造)を正しく理解することが重要です。賢明なレイアウトとは、潜在的な貢献者がコードの一部を探すために永遠に費やす必要がないことを意味します。ファイルの場所は直感的です。私たちは既存のプロジェクトを扱っているので、おそらく何かを移動する必要があるでしょう。

上から始めましょう。ほとんどのプロジェクトには、多数の最上位ファイル(setup.py、README.md、requirements.txtなど)があります。次に、すべてのプロジェクトが持つべき3つのディレクトリがあります。

  • プロジェクトドキュメントを含むdocsディレクトリ
  • 実際のPythonパッケージを格納するプロジェクトの名前が付けられたディレクトリ
  • 2つの場所のいずれかにあるテストディレクトリ
    • テストコードとリソースを含むパッケージディレクトリの下
    • スタンドアロンの最上位ディレクトリとしてファイルをどのように編成するかをよりよく理解するために、ここに私のプロジェクトの1つである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

ご覧のとおり、最上位のファイル、docsディレクトリ(sphinxが生成したドキュメントを置く空のディレクトリ)、sandmanディレクトリ、sandmanの下にtestディレクトリがあります。


4
私はこれを行いますが、それだけではありません。「virtualenv env」を自動化する「env」ターゲットを持つトップレベルのMakefileがあります。./env/bin/pip install -r requirements.txt; ./env/bin/python setup.py develop '、また通常はenvに依存し、テストの依存関係をインストールしてpy.testを実行する「テスト」ターゲット。
pjz 2014年

@pjzアイデアを広げていただけませんか?Makefileと同じレベルに置くことについて話していsetup.pyますか?だから私が理解したらmake env、新しいものの作成を正しく自動化し、それにvenvパッケージをインストールします...?
St.Antario

@ St.Antario正確に。前述のように、私は通常、テストを実行するための「テスト」ターゲットと、現在のタグを見てホイールを構築し、それをpypiに送信する「リリース」ターゲットも持っています。
pjz


19

python_boilerplateテンプレートを使用してプロジェクトを開始してみてください。これは主にベストプラクティスに従っていますが(例:ここにあるもの)、ある時点でプロジェクトを複数の卵に分割したいと思った場合に適しています(そして、最も単純なプロジェクト以外では、私を信じてください。一般的な状況は、ローカルで変更されたバージョンの誰かのライブラリを使用する必要がある場合です)。

  • ソースはどこに置きますか?

    • かなり大きなプロジェクトの場合、ソースをいくつかの卵に分割することは理にかなっています。各卵は、個別のsetuptools-layoutとしてに配置されPROJECT_ROOT/src/<egg_name>ます。
  • アプリケーションの起動スクリプトはどこに配置しますか?

    • 理想的なオプションは、アプリケーションの起動スクリプトをentry_point卵の1つとして登録することです。
  • IDEプロジェクトをどこに配置しますか?

    • IDEによって異なります。それらの多くはPROJECT_ROOT/.<something>、プロジェクトのルートに自分のものを保持していますが、これは問題ありません。
  • ユニット/受け入れテストはどこに置きますか?

    • 各卵は、そのPROJECT_ROOT/src/<egg_name>/testsディレクトリに保持されているテストの個別のセットを持っています。私は個人的にpy.testそれらを実行するために使用することを好みます。
  • 設定ファイルなどのPython以外のデータはどこに配置しますか?

    • 場合によります。Python以外のデータにはさまざまなタイプがあります。
      • 「リソース」、つまり卵内にパッケージ化する必要があるデータ。このデータは、パッケージの名前空間内のどこかにある対応するeggディレクトリに送られます。からのpkg_resourcesパッケージを介してsetuptools、またはPython 3.7以降importlib.resources、標準ライブラリのモジュールを介して使用できます。
      • 「Config-files」、つまりプロジェクトのソースファイルの外部と見なされる非Pythonファイルですが、アプリケーションの実行開始時にいくつかの値で初期化する必要があります。開発中、私はそのようなファイルをに保持することを好みますPROJECT_ROOT/config。展開にはさまざまなオプションがあります。Windowsの場合%APP_DATA%/<app-name>/config、Linuxの場合、/etc/<app-name>または/opt/<app-name>/config
      • 生成されたファイル、つまり、実行中にアプリケーションによって作成または変更される可能性のあるファイル。私はそれらをPROJECT_ROOT/var開発中、および/varLinuxの展開中は保持したいと思います。
  • pyd / soバイナリ拡張モジュール用のC ++などの非Pythonソースをどこに置きますか?
    • PROJECT_ROOT/src/<egg_name>/native

ドキュメンテーションは通常、PROJECT_ROOT/docまたはに含まれますPROJECT_ROOT/src/<egg_name>/doc(これは、卵の一部を個別の大きなプロジェクトと見なすかどうかによって異なります)。PROJECT_ROOT/buildout.cfgとのようなファイルに追加の設定がいくつかありPROJECT_ROOT/setup.cfgます。


素晴らしい答えをありがとう!あなたは私に多くのことを明確にしてくれました!卵を入れ子にすることはできますか?
Shookie 2014

いいえ、他の.eggファイル内に.eggファイルを格納するという意味で卵を「ネスト」することはできません。[本当に奇妙なことが起こらない限り]これが大いに役立つことを願っています。ただし、できることは、「仮想」卵を作成することです。これは、有用なコードを提供せず、依存関係リストに他のパッケージをリストする空のパッケージです。このようにして、ユーザーがそのようなパッケージをインストールしようとすると、依存する多くの卵を再帰的にインストールします。
KT。

@KTでは、生成されたデータの処理方法について少し詳しく説明できますか?特に、開発とデプロイメントを(コードで)どのように区別しますか?私はあなたには、いくつか持っている想像base_data_location変数を、しかし、どのように適切に設定するのですか?
cmyr 2016

1
私はあなたが「ランタイムデータ」について話していると思います-多くの場合、人々が/ var / packagenameまたは〜/ .packagename / varの下に置くもの、あるいはその他。ほとんどの場合、これらの選択は、ユーザーが変更する必要がないデフォルトとして十分です。この動作を調整できるようにしたい場合、オプションはかなり豊富であり、単一の当てはめはありません-すべてのベストプラクティス。一般的な選択:a)〜/ .packagename / configfile、b)export MY_PACKAGE_CONFIG = / path / to / configfile c)コマンドラインオプションまたは関数パラメーターd)これらの組み合わせ。
KT。

シングルトンのConfigクラスがどこかにあるのはごく普通のことであることに注意してください。このクラスは、お気に入りの設定ロードロジックを処理し、ユーザーが実行時に設定を変更できるようにすることもできます。しかし、一般的には、これは別の質問に値する問題だと思います(この質問はどこかで以前に尋ねられた可能性があります)。
KT。

15

私の経験では、それは反復の問題です。データとコードをどこにでも置くと思います。とにかく、あなたは間違っているでしょう。しかし、物事がどのように形作られるのかについて正確に理解できれば、この種の推測を行うためのはるかに優れた立場になります。

拡張ソースに関しては、pythonのディレクトリと他のさまざまな言語のディレクトリを含むトランクの下にコードディレクトリがあります。個人的には、次回、拡張コードを独自のリポジトリーに入れてみる傾向があります。

そうは言っても、私は最初のポイントに戻ります。あまり大きな取引をしないでください。それはあなたのために働くように見えるどこかにそれを置きます。機能しないものが見つかった場合は、変更することができます(変更する必要があります)。


うん。私はそれについて「Python的」にしようとします。明示的は暗黙的よりも優れています。ディレクトリ階層は、書き込まれるよりも読み取り/検査されます。等
エリック

10

Python以外のデータはpackage_datasetuptoolsのサポートを使用してPythonモジュール内にバンドルするのが最適です。名前空間パッケージを使用して、複数のプロジェクトが使用できる共有名前空間を作成することを強くお勧めします-パッケージを配置するJavaの規則com.yourcompany.yourproject(および共有できるcom.yourcompany.utils名前空間。

ブランチとマージを再作成します。十分なソース管理システムを使用している場合、名前変更によってもマージを処理します。バザールはこれが特に得意です。

ここでの他のいくつかの答えに反して、私はsrcディレクトリをトップレベルに持つことで+1しています(docそして、test横にディレクトリがあります)。ドキュメントディレクトリツリーの特定の規則は、使用しているものによって異なります。たとえばSphinxには、クイックスタートツールがサポートする独自の規則があります。

setuptoolsとpkg_resourcesを活用してください。これにより、他のプロジェクトがコードの特定のバージョンに依存することがはるかに容易になります(さらに、を使用している場合、複数のバージョンを異なる非コードファイルと共に同時にインストールすることができますpackage_data)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.