Wie organisieren Sie ein Python-Projekt, das mehrere Pakete enthält, sodass jede Datei in einem Paket noch einzeln ausgeführt werden kann?

TL; DR

Hier ist ein Beispielrepository, das wie im ersten Diagramm (unten) beschrieben eingerichtet ist:https: //github.com/Poddster/package_problem

Wenn Sie es in Bezug auf die Projektorganisation wie im zweiten Diagramm aussehen lassen und dennoch die folgenden Befehle ausführen können, haben Sie die Frage beantwortet:

$ git clone https://github.com/Poddster/package_problems.git
$ cd package_problems
<do your magic here>

$ nosetests

$ ./my_tool/my_tool.py
$ ./my_tool/t.py
$ ./my_tool/d.py

 (or for the above commands, $ cd ./my_tool/ && ./my_tool.py is also acceptable)

Alternativ: Geben Sie mir eine andere Projektstruktur, mit der ich zusammengehörige Dateien ('Paket') gruppieren, alle Dateien einzeln ausführen, die Dateien in andere Dateien im selben Paket importieren und die Pakete / Dateien in andere Pakete importieren kann Dateien.

Momentane Situatio

Ich habe ein paar Python-Dateien. Die meisten von ihnen sind nützlich, wenn sie über die Befehlszeile aufgerufen werden können, d. H. Sie verwenden alle argparse und if __name__ == "__main__" nützliche Dinge zu tun.

erzeit habe ich diese Verzeichnisstruktur und alles funktioniert einwandfrei:

.
├── config.txt
├── docs/
│   ├── ...
├── my_tool.py
├── a.py
├── b.py
├── c.py
├── d.py
├── e.py
├── README.md
├── tests
│   ├── __init__.py
│   ├── a.py
│   ├── b.py
│   ├── c.py
│   ├── d.py
│   └── e.py
└── resources
    ├── ...

Einige der Skripteimport Dinge aus anderen Skripten, um ihre Arbeit zu erledigen. Aber kein Skript ist nur eine Bibliothek, sie sind alle aufrufbar. z.B. Ich könnte @ aufruf./my_tool.py, ./a.by, ./b.py, ./c.py etc und sie würden nützliche Dinge für den Benutzer tun.

"my_tool.py" ist das Hauptskript, das alle anderen Skripte nutzt.

Was ich machen will

Ich möchte jedoch die Art und Weise ändern, in der das Projekt organisiert ist. Das Projekt selbst stellt ein gesamtes Programm dar, das vom Benutzer verwendet werden kann, und wird als solches vertrieben. Ich weiß jedoch, dass Teile davon später in verschiedenen Projekten nützlich sein werden. Daher möchte ich versuchen, die aktuellen Dateien in einem Paket zusammenzufassen. In naher Zukunft werde ich diesem Projekt auch andere Pakete hinzufügen.

Um dies zu vereinfachen, habe ich beschlossen, das Projekt in etwa wie folgt neu zu organisieren:

.
├── config.txt
├── docs/
│   ├── ...
├── my_tool
│   ├── __init__.py
│   ├── my_tool.py
│   ├── a.py
│   ├── b.py
│   ├── c.py
│   ├── d.py
│   ├── e.py
│   └── tests
│       ├── __init__.py
│       ├── a.py
│       ├── b.py
│       ├── c.py
│       ├── d.py
│       └── e.py
├── package2
│   ├── __init__.py
│   ├── my_second_package.py
|   ├── ...
├── README.md
└── resources
    ├── ...

Ich kann jedoch keine Projektorganisation finden, die die folgenden Kriterien erfüllt:

Alle Skripte können in der Befehlszeile aufgerufen werden (entweder alsmy_tool\a.py odercd my_tool && a.py)Die Tests laufen tatsächlich:)Dateien in package2 könnenimport my_tool

Das Hauptproblem liegt in den von den Paketen und den Tests verwendeten Importanweisungen.

erzeit tun alle Pakete, einschließlich der Tests, einfachimport <module> und es ist richtig gelöst. Aber wenn man Dinge herumwirbelt, funktioniert das nicht.

Bitte beachten Sie, dass die Unterstützung von py2.7 eine Voraussetzung ist, sodass alle Dateien @ habefrom __future__ import absolute_import, ... oben

Was ich versucht habe, und die katastrophalen Ergebnisse1

Wenn ich die Dateien wie oben gezeigt verschiebe, aber alle Importanweisungen unverändert lasse:

$ ./my_tool/*.py funktioniert und sie laufen alle richtig$ nosetests vom obersten Verzeichnis ausführen funktioniert nicht. Die Tests können die Paketskripte nicht importieren.pycharm hebt beim Bearbeiten dieser Dateien die Importanweisungen rot hervor: 2

Wenn ich dann die Testskripte ändere:

from my_tool import x
$ ./my_tool/*.py funktioniert immer noch und sie laufen alle richtig$ nosetests vom obersten Verzeichnis ausführen funktioniert nicht. Dann können Tests die richtigen Skripte importieren, aber die Importe in die Skripte selbst schlagen fehl, wenn die Testskripte sie importieren.pycharm hebt die Importanweisungen in den Hauptskripten noch rot hervor: 3

Wenn ich die gleiche Struktur behalte und änderealle seinfrom my_tool import dann

$ ./my_tool/*.py ergibtImportErrors$ nosetests läuft alles in Ordnung.pycharm beschwert sich über nichts

z.B. von 1.

Traceback (most recent call last):
  File "./my_tool/a.py", line 34, in <module>
    from my_tool import b
ImportError: cannot import name b
4

Ich habe es auch versuchtfrom . import x aber das endet nur mitValueError: Attempted relative import in non-package zum direkten Ausführen von Skripten.

ehen Sie sich einige andere SO-Antworten an:

Ich kann nicht einfach @ verwendpython -m pkg.tests.core_test wi

a) Ich habe keinMai .py. Ich denke, ich könnte eine haben?
b) Ich möchte alle Skripte ausführen können, nicht nur main?

Ich habe es versucht

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

aber es hat nicht geholfen.

Ich habe auch versucht:

__package__ = "my_tool"
from . import b

Aber erhalten:

SystemError: Parent module 'loading_tool' not loaded, cannot perform relative import

addingimport my_tool Vorfrom . import b endet gerade wieder mitImportError: cannot import name b

Fix

Was sind die richtigen magischen Beschwörungsformeln und das richtige Verzeichnislayout, damit all dies funktioniert?

Antworten auf die Frage(6)

Ihre Antwort auf die Frage