github submodule korrekt einbinden und verwenden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

Hallo zusammen,

ich habe zwei Python Projekte, und beide werden über github versioniert.
Projekt 1 ist als submodule definiert und korrekt importiert.

Ich habe jetzt das Problem, das submodule korrekt einzubinden und anzusprechen im 2. Projekt.

Desweiteren. Wenn ich im 2. Projekt (welches importiert) mir in der IDE das 1. Projekt (das importierte) anschaue, sind die dortigen Importe (from scr.***) als falsch (rot) markiert. Also irgendwas ist hier noch falsch, und das Netz hat bisher keine Antwort für mich. Hier gibts doch bestimmt einige, die diesen Weg der submodule ebenfalls gehen.

So importiere ich das submodule

Code: Alles auswählen

project_root = pathlib.Path(
    str(os.path.abspath(os.path.join(os.path.abspath(os.curdir), os.pardir)))
)
pyEDApiConnector = project_root.joinpath("pyEDApiConnector")
sys.path.insert(1, pyEDApiConnector)
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
Benutzeravatar
sparrow
User
Beiträge: 4540
Registriert: Freitag 17. April 2009, 10:28

Wenn du von "Submodulen" sprichst, sprichst dann von Python Modulen oder von den Git-Submodulen?
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

von den git-submodulen
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Immer noch die falsche Grundlage für sowas. curdir ist einfach ‚.‘, und damit löst du, wie schon wirklich erschöpfend besprochen, deine Pfade relativ zum Arbeitsverzeichnis auf. Und das ist nicht fix das Verzeichnis, in dem dein Projekt liegt.

Was die Frage angeht: nein, submodule benutze ich nicht für sowas. Sondern pip install -e. Das ist deiner IDE hoffentlich bekannt, und löst das Problem.
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

Auch mit "pip install -e <path>" funktioniert dies nicht.

Code: Alles auswählen

sys.path.append("pyEDApiConnector")
from pyEDApiConnector.src.connector.edsm.cubeApi import Cube
bringt die Fehlermeldung
ModuleNotFoundError: No module named 'src.connector'
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
Benutzeravatar
sparrow
User
Beiträge: 4540
Registriert: Freitag 17. April 2009, 10:28

Warum erweiterst du denn da den Pfad, in dem die Python-Module gesucht werden?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mit pip install -e kannst du dein Paket A, das eine Abhaengigkeit zu Projekt B darstellt, in dem virtualenv installieren, das deine IDE verwendet. Wenn das passiert ist, dann braucht es dafuer dieses sys.path-Gefummel eben genau nicht mehr. Denn dann kennt der Python Interpreter den Pfad, und die importe sollten funktionieren. Genauso wie die Code-Analyse der IDE.

Und auch hier arbeitest du wieder mit relativen Pfaden. Auch das geht wieder in die Hose. Also nochmal: relative Pfade, os.curpath inklusive, loesen sich immer zum Arbeitsverzeichnis auf. Das so zu benutzen *funktioniert nicht robust*.
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

sparrow hat geschrieben: Samstag 10. Dezember 2022, 16:21 Warum erweiterst du denn da den Pfad, in dem die Python-Module gesucht werden?
sorry, die Frage verstehe ich nicht. Was meinst Du?
Das importierte git-submodule hat die Struktur "project.scr.***" Wie soll ich denn sonst an die Klassen kommen.
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hier mal eine komplette session, mit der das klappt:

Code: Alles auswählen

deets@singlemalt:/tmp$ mkdir foobar
deets@singlemalt:/tmp$ cd foobar/
deets@singlemalt:/tmp/foobar$ submacs setup.py  # Siehe unter
deets@singlemalt:/tmp/foobar$ cd ..
deets@singlemalt:/tmp$ mkdir project
deets@singlemalt:/tmp$ cd project/
deets@singlemalt:/tmp/project$ pipenv --python 3.10
Creating a virtualenv for this project...
Pipfile: /tmp/project/Pipfile
Using /home/deets/.platformio/penv/bin/python3 (3.10.6) to create virtualenv...
⠇ Creating virtual environment...created virtual environment CPython3.10.6.final.0-64 in 501ms
  creator Venv(dest=/home/deets/.virtualenvs/project-snzxs1jS, clear=False, no_vcs_ignore=False, global=False, describe=CPython3Posix)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/deets/.local/share/virtualenv)
    added seed packages: pip==22.0.2, setuptools==59.6.0, wheel==0.37.1
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

✔ Successfully created virtual environment! 
Virtualenv location: /home/deets/.virtualenvs/project-snzxs1jS
Creating a Pipfile for this project...
deets@singlemalt:/tmp/project$ pipenv shell
Launching subshell in virtual environment...
 . /home/deets/.virtualenvs/project-snzxs1jS/bin/activate
(project) deets@singlemalt:/tmp/project$ cd ../foobar/
(project) deets@singlemalt:/tmp/foobar$ pip install -e .
Obtaining file:///tmp/foobar
  Preparing metadata (setup.py) ... done
Installing collected packages: foo
  Running setup.py develop for foo
Successfully installed foo-1.0.0
(project) deets@singlemalt:/tmp/foobar$ cd ../project/
(project) deets@singlemalt:/tmp/project$ python
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
>>> foo.bar()
I'm bar in /tmp/foobar/foo/__init__.py
Das dazugehoerige setup.py

Code: Alles auswählen

from setuptools import setup, find_packages

setup(
    name='foo',
    version='1.0.0',
    url='https://github.com/foo.git',
    author='Foo Bar',
    author_email='foo@bar.com',
    description='Description',
    packages=find_packages(),
)
Nachtrag: ich habe das Paket foo vergessen :oops:

In /tmp/foobar gibt's ein Verzeichnis foo, darin eine Datei __init__.py, und darin die Funktion bar:

Code: Alles auswählen

def bar():
    print(f"I'm bar in {__file__}")
Benutzeravatar
__blackjack__
User
Beiträge: 14069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`src` sollte auch nie ein Modul oder Package heissen. Wenn das Projekt `pyEDApiConnector` heisst und damit auch das Verzeichnis in dem alles liegt, und dort ein `src`-Verzsichnis drin liegt, dann sollte *dort* ein Package drin liegen das entsprechend heisst, also weder `src` selber noch einfach `connector`, sondern `EDApiConnector` oder so. Das `py` am Anfang kann man sich hier dann sparen, denn das ist ja ein Python-Package, da bringt es keinen Mehrwert da noch mal `py` in den Namen zu packen. Bei `cubeApi` (eigentlich `cube_api`) würde ich auch noch mal in mich gehen ob das API da tatsächlich im Namen stehen muss. Und eventuell auch gleich noch ob das tatsächlich ein eigenes Modul sein muss, falls da nur eine `Cube`-Klasse definiert wird. Ist ja Python und kein Java. Also:

Code: Alles auswählen

pyEdApiConnector/
    src/
        EDApiConnector/
            edsm/
                __init__.py
                cube.py
            __init__.py
    setup.py
    …
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

Wohin sollte denn das git-submodule importiert werden. In das Project-Root oder ins src -dir? Wie immer gibts im Netz dazu tausende versch. Antworten.

Und ich arbeite nicht mit setup.py sondern mit toml. Muss ich erstmal finden, wie ich es dort mit einbinde.
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn man das als submodule behalten will (weil man darueber zB die genutze Version definieren will), dann kann man das zB in ein Unterverzeichnis packen. Wir benutzen aus Konvention immer "modules", weil es einige etwas aergerliche Probleme mit submodulen geben kann, wenn man die nicht ganz sicher niemals mit einem gleich benannten Verzeichnis ersetzt.

Also zB sowas:

Code: Alles auswählen

/project/
    modules/daspaket
    src/projekt-das-daspaket-benutzt
Und Pakete definiert man in Python mit setup.py Ich weiss nicht, was du da fuer eine toml-Datei hast, aber das klingt nach deiner IDE. Das ist aber nicht massgeblich dafuer, was Python macht.
Benutzeravatar
__blackjack__
User
Beiträge: 14069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: `setup.py` war gestern, oder wird morgen zumindest gestern gewesen sein. `pyproject.toml` ist das neue `setup.py`. Hab's selbst noch nicht verwende, noch geht die `setup.py` ja.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Oh! Das war mir nicht bewusst. Aber dann sollte es ja im Grunde gleich gehen.
narpfel
User
Beiträge: 691
Registriert: Freitag 20. Oktober 2017, 16:10

pyproject.toml hatte sehr lange das Problem, dass damit keine editable installs gingen. Anscheinend geht das inzwischen, aber die entsprechende `pip`-Version ist gerade mal ein Jahr alt.

Also @icke das ist zumindest was zusätzliches, auf das du achten solltest. Du brauchst `pip` >= 21.3 für editable installs mit pyproject.toml-Projekten.
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

Inzwischen bin ich mehr als am verzweifeln.

Habe jetzt aufgrund Eurer Antworten umgebaut.

Code: Alles auswählen

project-root
  - modules (folder)
     - EdApiConnector (from git)
        - src (folder)
             - EdApiConnector (folder)
             	- quellcode (modules)
  - src (folder)
Die Imports/from im submodule sind alle kaputt. Werden schon als Fehler angezeigt. Ich bin kurz davor alles in einem Project zu händeln, was ich eigentlich nicht wollte.

Ein
pip install -e ./modules/EdApiConnector
gibt mir diesen Fehler

Code: Alles auswählen

error: subprocess-exited-with-error
Habt Ihr noch irgendwelche Tipps dazu?
Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du mal die volle Fehlermeldung & Inhalt der pyproject.toml?
Icke
User
Beiträge: 25
Registriert: Mittwoch 23. November 2022, 12:55

Da ich pyproject.toml dahingehend nicht konfigurieren konnte, habe ich auf setup.py umgestellt.

Fehlermeldung

Code: Alles auswählen

    writing top-level names to C:\Users\username\AppData\Local\Temp\pip-pip-egg-info-so8kc7zb\EdApiConnector.egg-info\top_level.txt  
      writing manifest file 'C:\Users\username\AppData\Local\Temp\pip-pip-egg-info-so8kc7zb\EdApiConnector.egg-info\SOURCES.txt'       
      error: package directory 'src\EDApiConnector\tests' does not exist
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.

setup.py den Hauptprojektes

Code: Alles auswählen

from setuptools import setup, find_packages

setup(
    name='EdExplorationPlanner',
    version='v0.0.1',
    packages=find_packages(include=['modules.*']),
    package_dir={'': 'src'},
    url='https://github.com/username/EdExplorationPlanner',
    license='MIT',

    description='Elite Dangerous Expedition Planner'
)

setup.py des submodules

Code: Alles auswählen

from setuptools import setup, find_packages

setup(
    name='EdApiConnector',
    version='v0.0.1',
    packages=find_packages(),
    package_dir={'': 'src/EDApiConnector'},
    url='https://github.com/username/EdApiConnector',
    license='MIT',
    author_email='',
    description='Elite Dangerous Api Connector',
    install_requires=['requests']
)

Greetings -=Icke=-

I do this just for fun, not professionell
only Python and absolute beginner
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich versuche nacher mal ein Beispiel, aber was sofort auffaellt: das packages im oberen setup.py ist Quatsch. Du willst dort doch nur ein "requires" haben, das deinen EdApiConnector benennt. Und du solltest den auch konsistent bennen, Ed... oder ED..., nicht beides.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

So, das ganze funktioniert problemlos:

Code: Alles auswählen

dir@thunderjaw:/tmp/ed-exploration-planner$  . /home/dir/.local/share/virtualenvs/ed-exploration-planner-LMv8CBpM/bin/activate
(ed-exploration-planner) dir@thunderjaw:/tmp/ed-exploration-planner$ pip install -e modules/ed-api-connector
Obtaining file:///tmp/ed-exploration-planner/modules/ed-api-connector
  Preparing metadata (setup.py) ... done
Installing collected packages: EDApiConnector
  Running setup.py develop for EDApiConnector
Successfully installed EDApiConnector-0.0.1
(ed-exploration-planner) dir@thunderjaw:/tmp/ed-exploration-planner$ pip install -e .
Obtaining file:///tmp/ed-exploration-planner
  Preparing metadata (setup.py) ... done
Installing collected packages: EDExplorationPlanner
  Running setup.py develop for EDExplorationPlanner
Successfully installed EDExplorationPlanner-0.0.1
(ed-exploration-planner) dir@thunderjaw:/tmp/ed-exploration-planner$ edp
/tmp/ed-exploration-planner/modules/ed-api-connector/src/EDApiConnector/__init__.py
(ed-exploration-planner) dir@thunderjaw:/tmp/ed-exploration-planner$ 
Wichtig sind konsistente Namen, und natuerlich die richtigen Schluesselworte und Verzeichnisse.

https://www.dropbox.com/s/lk1ts48w8dx1r ... r.tgz?dl=0

Ich habe hier die nicht-konformen Namen EDExplorationPlanner etc. genutzt. Das sollte alles kleingeschrieben sein. Und ggf. ueber Namensraum-Pakete nachgedacht werden.
Antworten