ubuntuusers.de

Python in PostgreSQL: eigenes Modul wo speichern?

Status: Gelöst | Ubuntu-Version: Server 19.10 (Eoan Ermine)
Antworten |

Redoute

Anmeldungsdatum:
21. Oktober 2005

Beiträge: 35

Hallo,

bei plpython3u in PostgreSQL vermisse ich in sys.path ein 'site-packages':

1
['/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7/dist-packages', '/usr/lib/python3/dist-packages']

Ich möchte ein paar eigene Funktionen als Modul zur Verfügung stellen, wie gehe ich da am Besten vor?

Danke und schöne Feiertage, Redoute

Bearbeitet von rklm:

Python-Formatierung

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

bei plpython3u in PostgreSQL vermisse ich in sys.path ein 'site-packages':

Verstehe ich nicht...

Ich möchte ein paar eigene Funktionen als Modul zur Verfügung stellen, wie gehe ich da am Besten vor?

Das empfohlene Vorgehen ist hier dokumentiert: https://packaging.python.org/

Gruß, noisefloor

Redoute

(Themenstarter)

Anmeldungsdatum:
21. Oktober 2005

Beiträge: 35

noisefloor schrieb:

Verstehe ich nicht...

Ich suche ein Verzeichnis, wo ich mein Modul "mymodule.py" speichern kann, sodass es

  1. von "import mymodule" ohne path-Manipulation gefunden wird,

  2. bei Python-Updates nicht verloren geht.

Die Verzeichnisnamen in sys.path enthalten entweder "dist-packages" oder "python3.7". Beides verstehe ich als Hinweis, dass die zweite Bedingung ggf. nicht erfüllt ist. Von Windows/Anaconda kenne ich es so, dass ich meine Module z. B. in C:\Anaconda\Lib\site-packages speichere.

Das empfohlene Vorgehen ist hier dokumentiert: https://packaging.python.org/

Hm, Python modules passt, lässt aber auch die Frage offen, wohin das Modul dann gespeichert werden soll.

Ich versuche gerade, https://docs.python.org/3/library/site.html zu verstehen. site.getsitepackages() ist

1
['/usr/local/lib/python3.7/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.7/dist-packages']

und site.getusersitepackages() ist

1
'/var/lib/postgresql/.local/lib/python3.7/site-packages'

Die beiden zusätzlich vorgesehenen Pfade scheinen mir auch nicht "besser".

Ich versuche es jetzt mit /usr/local/lib/python3.7/dist-packages, das ist ansonsten leer. Mal schauen, ob das mal nach Python 3.8 übernommen wird.

Danke und fröhliches Weiterfeiern, Redoute

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

...wo ich mein Modul "mymodule.py" speichern kann, sodass es...

Geht nicht. Grund: du musst das Modul für jede Python-Version separat installieren. Was durchaus auch sinnvoll ist.

Was du machen kannst: leg' es in der gleiche Verzeichnis wie dein Skript, dann wird es immer gefunden. Das ist dann aber streng genommen kein "installieren".

lässt aber auch die Frage offen, wohin das Modul dann gespeichert werden soll.

Nein, dass kannst du nämlich gar nicht festlegen. Python-Module installiert man üblicherweise mit pip und dann hängt der Speicherort z.B. davon ab, ob pip mit der Option --user aufgerufen wird oder nicht. Was du als Modul-Ersteller gar nicht beeinflussen kannst. Und wenn du pip in einem venv ausführst, ist der Speicherort nochmal anders. Gefunden wird das Modul aber trotzdem von jeweiligen Interpreter ☺

BTW: das ist unter Windows vom Prinzip auch nicht anders, nur das die Pfade halt anders sind.

Gruß, noisefloor

Redoute

(Themenstarter)

Anmeldungsdatum:
21. Oktober 2005

Beiträge: 35

noisefloor schrieb:

Das ist dann aber streng genommen kein "installieren".

Jetzt werden wir uns langsam einig. ☺ Ich will eigentlich nur einen geeigneten Platz zum Speichern.

Was du machen kannst: leg' es in der gleiche Verzeichnis wie dein Skript, dann wird es immer gefunden.

"Mein Skript" ist in der Regel keine Datei auf Ubuntu. Vor allem: Bei dem durch das System eingerichteten sys.path (siehe oben) ist das aktuelle Verzeichnis ('') nicht enthalten, das wäre sonst wohl lt. os.getcwd() das PGDATA-Verzeichnis.

Zum Beispiel schicke ich an den PostgreSQL-Server diese Abfrage:

1
2
3
4
DO $$
import mytools
mytools.write_gpkg('schema.table')
$$ LANGUAGE plpython3u;

Die (PostGIS-) Tabelle wird dann als Geopackage auf einem NAS abgespeichert. Funktioniert soweit auch, das Modul liegt halt jetzt in /usr/local/lib/python3.7/dist-packages.

Danke, Redoute!

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

das Verzeichnis, in dem das Skript liegt, ist automatisch der 1. Suchpfad. Siehe auch: https://docs.python.org/3/tutorial/modules.html#the-module-search-path

Gruß, noisefloor

Redoute

(Themenstarter)

Anmeldungsdatum:
21. Oktober 2005

Beiträge: 35

noisefloor schrieb:

das Verzeichnis, in dem das Skript liegt, ist automatisch der 1. Suchpfad.

  1. Bei plpython3u ist das aktuelle Verzeichnis nicht der erste Suchpfad. sys.path enthält kein ''. *)

  2. Es gibt kein "Verzeichnis, in dem das Skript liegt". Aktuelles Verzeichnis (os.getcwd()) ist das pgdata-Verzeichnis.

Ich habs gerade ausprobiert: testmodule.py in pgdata erstellt, PostgreSQL neu gestartet, import testmodule schlägt fehl. Erst nach sys.path.append('') funktioniert import testmodule.

Siehe auch: https://docs.python.org/3/tutorial/modules.html#the-module-search-path

Redoute

*) Auch nicht bei einem älteren PostgreSQL in Windows: ['C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\lib\\site-packages\\distribute-0.6.49-py3.3.egg', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\lib\\site-packages\\pip-8.1.2-py3.3.egg', 'C:\\EnterpriseDB\\LanguagePack\\9.4\\x64\\Python-3.3\\python33.zip', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\DLLs', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\lib', 'C:\\Program Files\\PostgreSQL\\9.6\\bin', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\lib\\site-packages', 'C:\\edb\\languagepack-9.6\\x64\\Python-3.3\\lib\\site-packages\\setuptools-0.6c11-py3.3.egg-info']

sebix Team-Icon

Moderator, Webteam

Anmeldungsdatum:
14. April 2009

Beiträge: 5582

Redoute schrieb:

noisefloor schrieb:

das Verzeichnis, in dem das Skript liegt, ist automatisch der 1. Suchpfad.

  1. Bei plpython3u ist das aktuelle Verzeichnis nicht der erste Suchpfad. sys.path enthält kein ''. *)

Hast du den Link angesehen? Dann wuesstest du naemlich, dass das falsch ist.

Anyway, die sauberste und einfachste Variante ist immernoch, das Skript ordentlich via pip install lokal zu installieren, oder auch "nur" via pip install -e lokal zu "verlinken".

Redoute

(Themenstarter)

Anmeldungsdatum:
21. Oktober 2005

Beiträge: 35

sebix schrieb:

das Verzeichnis, in dem das Skript liegt, ist automatisch der 1. Suchpfad.

  1. Bei plpython3u ist das aktuelle Verzeichnis nicht der erste Suchpfad. sys.path enthält kein ''. *)

Hast du den Link angesehen? Dann wuesstest du naemlich, dass das falsch ist.

Habe ich. Und ich habe mehrfach gezeigt, dass plpython3u offensichtlich das aktuelle Verzeichnis aus dem Suchpfad rausnimmt. Vermutlich aus Sicherheitserwägungen, obwohl: Wer Zugriff auf ein PostgreSQL mit Python hat, hat Zugriff auf den Host mit den Rechten von Konto postgres. Deswegen das "u" in "plpython3u".

Wenn das falsch ist: In welches Verzeichnis, das nicht im eingangs genannten sys.path enthalten ist, soll ich mytools.py denn legen, damit folgendes in einer SQL-Abfrage funktioniert? Es geht doch um "The directory containing the input script (or the current directory when no file is specified)", also die Ausgabe von os.getcwd()? __file__ ist natürlich nicht definiert.

1
2
3
4
DO $$
import mytools
mytools.write_gpkg('schema.table')
$$ LANGUAGE plpython3u;

Anyway, die sauberste und einfachste Variante ist immernoch, das Skript ordentlich via pip install lokal zu installieren, oder auch "nur" via pip install -e lokal zu "verlinken".

Nur um eine einzelne Moduldatei an "die richtige Stelle" zu kopieren? In welches Verzeichnis würde pip denn installieren? Vermutlich eines der "site-packages"?

Ich wollte gerade testen, was ein "pip3 install hello-world" macht, aber das ist gar nicht installiert, und ein "sudo apt install python3-pip" will mir gleich eine ganze Entwicklungsumgebung von über 200 MB aufdrücken.

Vielen Dank und frohes neues Jahr, Redoute

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

Es geht doch um "The directory containing the input script (or the current directory when no file is specified)", also die Ausgabe von os.getcwd()? file ist natürlich nicht definiert.

Richtig, weil du ja in dem Sinn kein Python-Skript hast, sondern Python Code in eine PostgreSQL Funktion einbaust. War aber - mir zumindest - anfangs nicht wirklich klar.

Damit wäre es IMHO am einfachsten, wenn du das Skript in ein Verzeichnis deiner Wahl legst und _vor_ dem import-Statement sys.path um das Verzeichnis erweiterst.

und ein "sudo apt install python3-pip" will mir gleich eine ganze Entwicklungsumgebung von über 200 MB aufdrücken.

Nee, keine IDE, sondern ein paar Compiler und Header-Files. Die brauchst du auch, weil pip dazu in der Lage ist, bei der Installation eines Python-Moduls falls notwendig C-Extensions für das Modul zu kompilieren.

Gruß, noisefloor

sebix Team-Icon

Moderator, Webteam

Anmeldungsdatum:
14. April 2009

Beiträge: 5582

Hast du schon versucht die Umgebungsvariablen so zu setzen, dass die imports klappen? https://www.postgresql.org/docs/current/plpython-envar.html

Antworten |