Pfade, Modulnamen und import-Statements

Hallo, ich hab mal eine Verständnisfrage. Gegeben sei ein Verzeichnis . und ein Programm ./keks. Weiterhin sei die Klasse MyClass1 in d/mc1.py und die Klasse MyClass2 in d/mc2.py definierrt. Wenn ich nun in keks die Klasse MyClass2 benutzen möchte, schreibe ich "from d.mc2 import MyClass2". Wnn ich in d/mc1.py dasselbe tun möchte, muss ich dort "from mc2 import MyClass2" schreiben, kann also Code, der "verwandte" Module benutzt, nicht frei verschieben. Ist das so gedacht, oder verpass ich da was? Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Am 04.05.24 um 13:12 schrieb Marc Haber:
Wnn ich in d/mc1.py dasselbe tun möchte, muss ich dort "from mc2 import MyClass2" schreiben,
Ich vermute, Du musst "from ..mc2 import …" schreiben, da Du das Modul relativ zu mc1 "adressieren" musst. Falls es bei Dir ohne ".." ist irgendwas faul.
-- Regards Hartmut Goebel | Hartmut Goebel |h.goebel@crazy-compilers.com | |www.crazy-compilers.com | compilers which you thought are impossible |

On Sat, May 04, 2024 at 07:22:52PM +0200, Hartmut Goebel wrote:
Das funktioniert so wie ich es geschrieben habe. Im etwas konkreteren Fall: [37/5247]mh@swivel:~/git/zg2dns $ grep -E 'class|import' get-root zg2dns/* get-root:from zg2dns.rootdata import DNSRootDataParser zg2dns/query.py:from rootdata import DNSRootDataParser zg2dns/query.py:class Zg2DNSQuery: zg2dns/rootdata.py:class DNSRootDataParser: Sowohl der Code in zg2dns/query-py als auch der code in get-root benutzen die Klasse DNSRootDataParser, und das funktioniert auch: 2 [38/5247]mh@swivel:~/git/zg2dns $ zg2dns/query.py 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:309 - rootservers.get_ipv4_servers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33'] 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:310 - rootservers.get_ipv6_servers()=['2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:311 - rootservers.get_all_servers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] 2024-05-05 10:07:50.361 | DEBUG | __main__:<module>:312 - rootservers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] [39/5247]mh@swivel:~/git/zg2dns $ ./get-root IPv4 Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33'] IPv6 Root Servers: ['2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] All Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e','2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] All Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e','2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] [40/5247]mh@swivel:~/git/zg2dns $ Die Notation ..irgendwas ist also nicht notwendig.
Ich finde es wenig schön dass man abhängig vom Ort der Nutzung unterschiedliche Import-Statements schreiben muss, aber wenn das so ist kann ich damit leben. Ich hatte das Verhalten halt nicht für pythonisch gehalten. In dnspython ist das auch nicht so geschrieben, z.B. steht in /usr/lib/python3/dist-packages/dns/resolver.py immer das Predix dns in den Imports dabei. Das funktioniert vermutlich, weil /usr/lib/python3/dist-packages im Pythonpath steht. Wäre ich dnspython-Entwickler, hätte ich ja meine workingcopy von mir aus unter ~/git/dnspython ausgecheckt, und wenn ich irgendwas ausprobiere, würde das "import dns.query" in ~/git/dnspython/dns/resolver.py ja das dns/query.py aus dem Pythonpath anziehen und nicht das aus meiner Workingcopy, weil ich ja sicher auch die Releaseversion der Library installiert hätte. Wir arbeiten Modulentwicker in so einer Situation? Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Marc Haber wrote:
Versuche mal "zg2dns.query" zu importieren: | Traceback (most recent call last): | File "/tmp/t/test", line 3, in <module> | import zg2dns.query | File "/tmp/t/zg2dns/query.py", line 1, in <module> | from rootdata import DNSRootDataParser | ModuleNotFoundError: No module named 'rootdata'
Dein Fehler ist ein komplett anderer. Der Python-Interpreter fügt das Verzeichnis, in dem das aktuelle Script liegt, dem Suchpfad hinzu. Rufst du "get-root" auf, dann ist es ".". Damit findet "import zg2dns.rootdata" auch "zg2dns/rootdata.py". Rufst du aber "zg2dns/query.py" direkt auf, dann ist auf einmal das Verzeichnis "zg2dns" im Suchpfad. Also referenziert "import rootdata" auf einmal was anderes.
Dafür gibt es "pip install -e ." z.B. Damit macht man das aktuelle Projekt im globalen Suchpfad des benutzten Interpreters verfügbar.
Wir arbeiten Modulentwicker in so einer Situation?
Module werden nicht als Scripte direkt aufgerufen, sind also auch nie ausführbar. Statt dessen werden sie mittels "python3 -m" aufgerufen. Im nächsten Schritt kommen dann Entry-Points, aus denen dann Scripte entstehen, welche in $prefix/bin landen. Bastian

On Sun, May 05, 2024 at 10:32:28AM -0000, Bastian Blank wrote:
Wo?
Also muss ich abhängig von dem Ort wo mein Skript liegt unterschiedliche import-Statements benutzen, das finde ich mindestens unschön. Aber jetzt wo ich es weiß kann ich aes natürlich machen.
Dafür gibt es "pip install -e ." z.B. Damit macht man das aktuelle Projekt im globalen Suchpfad des benutzten Interpreters verfügbar.
Aber hoffentlich nur im Environment einer Subshell? Oder ist das persistentes Herumfummeln im System? Wenn ja, wo?
Das Python Tutorial Kapitel 6.1.1 "Executing modules as scripts" stelt das als ganz praktisches Feature dar. Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Am 10.05.24 um 11:37 schrieb Marc Haber:
pip install installiert per default nach /usr/lib/pythonX.YZ/site-packages. Debian lässt das aber gar nicht mehr zu. Wenn ein virtual environment aktiv ist, wird nach <venv>/lib/pythonX.YZ/site-packages installliert. Dito bei nicht-aktivem vend und "<venv>/bin/pip install". Option --user installiert nach $HOME/.local/lib/pythonX.YZ/site-packages. pip list zeigt Dir, was wo installiert ist. (Bei aktivem venv aber im venv und nicht im System.) -- Regards Hartmut Goebel | Hartmut Goebel |h.goebel@crazy-compilers.com | |www.crazy-compilers.com | compilers which you thought are impossible |

On 2024-05-04 11:12, Marc Haber <mh+python-de@zugschlus.de> wrote:
Nein, das funktioniert nicht: #v+ % ./keks Traceback (most recent call last): File "/home/hjp/tmp/marc/./keks", line 3, in <module> from d.mc1 import MyClass1 File "/home/hjp/tmp/marc/d/mc1.py", line 1, in <module> from mc2 import MyClass2 ModuleNotFoundError: No module named 'mc2' #v- Es muss #v+ from d.mc2 import MyClass2 #v- heißen. Ob Du das Modul von keks oder von einem anderen Modul aus importierst, macht keinen Unterschied.
Wie Hartmut schon geschrieben hat, kannst Du relative Imports verwendenm, hier also #v+ from .mc2 import MyClass2 #v- Ob das für Deinen Code sinnvoll ist, musst du selbst entscheiden. hp

On Sun, May 05, 2024 at 02:26:02AM +0200, Peter J. Holzer wrote:
Mein mc1.py hat eingebauten testcode: #v+ if __name__ == "__main__": zdns = Zg2DNSQuery(timeout=2, debug=True) rootservers = DNSRootDataParser() logger.debug(f"{rootservers.get_ipv4_servers()=}") #v- verhält sich der vielleicht anders als wenn man nur das Modul importiert? Das wäre dann ja noch viel schlimmer ;-) Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

On 2024-05-05 08:25, Marc Haber <mh+python-de@zugschlus.de> wrote:
Ah, dachte ich mir, dass da eine wichtige Information fehlt ;-).
verhält sich der vielleicht anders als wenn man nur das Modul importiert? Das wäre dann ja noch viel schlimmer ;-)
Wenn Du ein Script aufrufst, wird das Directory des Scripts in sys.path eingefügt. Dadurch wird dann bei einem "import m" u.a. auch nach "full_path_to_script_dir/m.py" gesucht und damit funktioniert der Import. Zum Testen von komplexeren Packages ist das aber wenig hilfreich, weil im echten Einsatz natürlich nicht irgendwelche Subdirectorys der Package-Hierarchie im Suchpfad stehen und man, wenn man ein Modul aus einem Package direkt aufruft, die Package-Hierarchie verliert und damit relative Imports nicht funktionieren: #v+ % python3 d/mc1.py __main__ ['/home/hjp/tmp/marc/d', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/hjp/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages'] Traceback (most recent call last): File "/home/hjp/tmp/marc/d/mc1.py", line 4, in <module> from .mc2 import MyClass2 ImportError: attempted relative import with no known parent package #v- Unter anderem auch aus diesem Grund schreibe ich Test-Code immer in eigene Files. hp

On Sun, May 05, 2024 at 12:38:18PM +0200, Peter J. Holzer wrote:
Welche? Dass ich den Empfehlungen des Python Tutorials, Kapitel 6.1.1 "Executing modules as scripts" gefolgt bin? War das falsch?
Unter anderem auch aus diesem Grund schreibe ich Test-Code immer in eigene Files.
So werde ich das dann jetzt wohl auch halten. Schade. Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

On 2024-05-10 09:39, Marc Haber <mh+python-de@zugschlus.de> wrote:
Die Information, dass Du das gleiche Python-File einmal mittels import und einmal als Script ausführst. Das sind unterschiedliche Mechanismen.
Dass ich den Empfehlungen des Python Tutorials, Kapitel 6.1.1 "Executing modules as scripts" gefolgt bin? War das falsch?
Das funktioniert in einigen einfachen Fällen (insbesondere, wenn das Modul keine weiteren Imports (außer Standard-Modulen) hat oder wenn die alle direkt im Suchpfad liegen. Wenn man das mit einem Submodul eines Packages probiert, muss man sich das Environment entsprechend herrichten (z.B. indem man $PYTHONPATH passend setzt). Keine große Hexerei, wenn man es weiß, aber selbst dann vergisst man gerne darauf (ich zumindest). Ich würde daher davon abraten. hp

Am 04.05.24 um 13:12 schrieb Marc Haber:
Bei Pfadproblemen verwende ich sys.path.append( Hermann der das #include ../ich.h für gemeinsames vermisst. -- <http://www.hermann-riemann.de>

On Sun, May 05, 2024 at 12:02:34PM +0200, Hermann Riemann wrote:
Bei Pfadproblemen verwende ich sys.path.append(
In Klassen- und Moduldefinitionen und importen? Echt jetzt? Oder hast Du nur die Frage nicht verstanden? Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Am 04.05.24 um 13:12 schrieb Marc Haber:
Ein wenig lässt sich mit sys.path.append erreichen. Ich benutze das für meine Hilfsprogramme, die von mehreren Programme verwendet werden. -- <http://www.hermann-riemann.de>

Am 04.05.24 um 13:12 schrieb Marc Haber:
Wnn ich in d/mc1.py dasselbe tun möchte, muss ich dort "from mc2 import MyClass2" schreiben,
Ich vermute, Du musst "from ..mc2 import …" schreiben, da Du das Modul relativ zu mc1 "adressieren" musst. Falls es bei Dir ohne ".." ist irgendwas faul.
-- Regards Hartmut Goebel | Hartmut Goebel |h.goebel@crazy-compilers.com | |www.crazy-compilers.com | compilers which you thought are impossible |

On Sat, May 04, 2024 at 07:22:52PM +0200, Hartmut Goebel wrote:
Das funktioniert so wie ich es geschrieben habe. Im etwas konkreteren Fall: [37/5247]mh@swivel:~/git/zg2dns $ grep -E 'class|import' get-root zg2dns/* get-root:from zg2dns.rootdata import DNSRootDataParser zg2dns/query.py:from rootdata import DNSRootDataParser zg2dns/query.py:class Zg2DNSQuery: zg2dns/rootdata.py:class DNSRootDataParser: Sowohl der Code in zg2dns/query-py als auch der code in get-root benutzen die Klasse DNSRootDataParser, und das funktioniert auch: 2 [38/5247]mh@swivel:~/git/zg2dns $ zg2dns/query.py 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:309 - rootservers.get_ipv4_servers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33'] 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:310 - rootservers.get_ipv6_servers()=['2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] 2024-05-05 10:07:50.360 | DEBUG | __main__:<module>:311 - rootservers.get_all_servers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] 2024-05-05 10:07:50.361 | DEBUG | __main__:<module>:312 - rootservers()=['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] [39/5247]mh@swivel:~/git/zg2dns $ ./get-root IPv4 Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33'] IPv6 Root Servers: ['2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e', '2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] All Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e','2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] All Root Servers: ['198.41.0.4', '199.9.14.201', '192.33.4.12', '199.7.91.13', '192.203.230.10', '192.5.5.241', '192.112.36.4', '198.97.190.53', '192.36.148.17', '192.58.128.30', '193.0.14.129', '199.7.83.42', '202.12.27.33', '2001:503:ba3e::2:30', '2001:500:200::b', '2001:500:2::c', '2001:500:2d::d', '2001:500:a8::e','2001:500:2f::f', '2001:500:12::d0d', '2001:500:1::53', '2001:7fe::53', '2001:503:c27::2:30', '2001:7fd::1', '2001:500:9f::42', '2001:dc3::35'] [40/5247]mh@swivel:~/git/zg2dns $ Die Notation ..irgendwas ist also nicht notwendig.
Ich finde es wenig schön dass man abhängig vom Ort der Nutzung unterschiedliche Import-Statements schreiben muss, aber wenn das so ist kann ich damit leben. Ich hatte das Verhalten halt nicht für pythonisch gehalten. In dnspython ist das auch nicht so geschrieben, z.B. steht in /usr/lib/python3/dist-packages/dns/resolver.py immer das Predix dns in den Imports dabei. Das funktioniert vermutlich, weil /usr/lib/python3/dist-packages im Pythonpath steht. Wäre ich dnspython-Entwickler, hätte ich ja meine workingcopy von mir aus unter ~/git/dnspython ausgecheckt, und wenn ich irgendwas ausprobiere, würde das "import dns.query" in ~/git/dnspython/dns/resolver.py ja das dns/query.py aus dem Pythonpath anziehen und nicht das aus meiner Workingcopy, weil ich ja sicher auch die Releaseversion der Library installiert hätte. Wir arbeiten Modulentwicker in so einer Situation? Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Marc Haber wrote:
Versuche mal "zg2dns.query" zu importieren: | Traceback (most recent call last): | File "/tmp/t/test", line 3, in <module> | import zg2dns.query | File "/tmp/t/zg2dns/query.py", line 1, in <module> | from rootdata import DNSRootDataParser | ModuleNotFoundError: No module named 'rootdata'
Dein Fehler ist ein komplett anderer. Der Python-Interpreter fügt das Verzeichnis, in dem das aktuelle Script liegt, dem Suchpfad hinzu. Rufst du "get-root" auf, dann ist es ".". Damit findet "import zg2dns.rootdata" auch "zg2dns/rootdata.py". Rufst du aber "zg2dns/query.py" direkt auf, dann ist auf einmal das Verzeichnis "zg2dns" im Suchpfad. Also referenziert "import rootdata" auf einmal was anderes.
Dafür gibt es "pip install -e ." z.B. Damit macht man das aktuelle Projekt im globalen Suchpfad des benutzten Interpreters verfügbar.
Wir arbeiten Modulentwicker in so einer Situation?
Module werden nicht als Scripte direkt aufgerufen, sind also auch nie ausführbar. Statt dessen werden sie mittels "python3 -m" aufgerufen. Im nächsten Schritt kommen dann Entry-Points, aus denen dann Scripte entstehen, welche in $prefix/bin landen. Bastian

On Sun, May 05, 2024 at 10:32:28AM -0000, Bastian Blank wrote:
Wo?
Also muss ich abhängig von dem Ort wo mein Skript liegt unterschiedliche import-Statements benutzen, das finde ich mindestens unschön. Aber jetzt wo ich es weiß kann ich aes natürlich machen.
Dafür gibt es "pip install -e ." z.B. Damit macht man das aktuelle Projekt im globalen Suchpfad des benutzten Interpreters verfügbar.
Aber hoffentlich nur im Environment einer Subshell? Oder ist das persistentes Herumfummeln im System? Wenn ja, wo?
Das Python Tutorial Kapitel 6.1.1 "Executing modules as scripts" stelt das als ganz praktisches Feature dar. Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Am 10.05.24 um 11:37 schrieb Marc Haber:
pip install installiert per default nach /usr/lib/pythonX.YZ/site-packages. Debian lässt das aber gar nicht mehr zu. Wenn ein virtual environment aktiv ist, wird nach <venv>/lib/pythonX.YZ/site-packages installliert. Dito bei nicht-aktivem vend und "<venv>/bin/pip install". Option --user installiert nach $HOME/.local/lib/pythonX.YZ/site-packages. pip list zeigt Dir, was wo installiert ist. (Bei aktivem venv aber im venv und nicht im System.) -- Regards Hartmut Goebel | Hartmut Goebel |h.goebel@crazy-compilers.com | |www.crazy-compilers.com | compilers which you thought are impossible |

On 2024-05-04 11:12, Marc Haber <mh+python-de@zugschlus.de> wrote:
Nein, das funktioniert nicht: #v+ % ./keks Traceback (most recent call last): File "/home/hjp/tmp/marc/./keks", line 3, in <module> from d.mc1 import MyClass1 File "/home/hjp/tmp/marc/d/mc1.py", line 1, in <module> from mc2 import MyClass2 ModuleNotFoundError: No module named 'mc2' #v- Es muss #v+ from d.mc2 import MyClass2 #v- heißen. Ob Du das Modul von keks oder von einem anderen Modul aus importierst, macht keinen Unterschied.
Wie Hartmut schon geschrieben hat, kannst Du relative Imports verwendenm, hier also #v+ from .mc2 import MyClass2 #v- Ob das für Deinen Code sinnvoll ist, musst du selbst entscheiden. hp

On Sun, May 05, 2024 at 02:26:02AM +0200, Peter J. Holzer wrote:
Mein mc1.py hat eingebauten testcode: #v+ if __name__ == "__main__": zdns = Zg2DNSQuery(timeout=2, debug=True) rootservers = DNSRootDataParser() logger.debug(f"{rootservers.get_ipv4_servers()=}") #v- verhält sich der vielleicht anders als wenn man nur das Modul importiert? Das wäre dann ja noch viel schlimmer ;-) Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

On 2024-05-05 08:25, Marc Haber <mh+python-de@zugschlus.de> wrote:
Ah, dachte ich mir, dass da eine wichtige Information fehlt ;-).
verhält sich der vielleicht anders als wenn man nur das Modul importiert? Das wäre dann ja noch viel schlimmer ;-)
Wenn Du ein Script aufrufst, wird das Directory des Scripts in sys.path eingefügt. Dadurch wird dann bei einem "import m" u.a. auch nach "full_path_to_script_dir/m.py" gesucht und damit funktioniert der Import. Zum Testen von komplexeren Packages ist das aber wenig hilfreich, weil im echten Einsatz natürlich nicht irgendwelche Subdirectorys der Package-Hierarchie im Suchpfad stehen und man, wenn man ein Modul aus einem Package direkt aufruft, die Package-Hierarchie verliert und damit relative Imports nicht funktionieren: #v+ % python3 d/mc1.py __main__ ['/home/hjp/tmp/marc/d', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/hjp/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages'] Traceback (most recent call last): File "/home/hjp/tmp/marc/d/mc1.py", line 4, in <module> from .mc2 import MyClass2 ImportError: attempted relative import with no known parent package #v- Unter anderem auch aus diesem Grund schreibe ich Test-Code immer in eigene Files. hp

On Sun, May 05, 2024 at 12:38:18PM +0200, Peter J. Holzer wrote:
Welche? Dass ich den Empfehlungen des Python Tutorials, Kapitel 6.1.1 "Executing modules as scripts" gefolgt bin? War das falsch?
Unter anderem auch aus diesem Grund schreibe ich Test-Code immer in eigene Files.
So werde ich das dann jetzt wohl auch halten. Schade. Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

On 2024-05-10 09:39, Marc Haber <mh+python-de@zugschlus.de> wrote:
Die Information, dass Du das gleiche Python-File einmal mittels import und einmal als Script ausführst. Das sind unterschiedliche Mechanismen.
Dass ich den Empfehlungen des Python Tutorials, Kapitel 6.1.1 "Executing modules as scripts" gefolgt bin? War das falsch?
Das funktioniert in einigen einfachen Fällen (insbesondere, wenn das Modul keine weiteren Imports (außer Standard-Modulen) hat oder wenn die alle direkt im Suchpfad liegen. Wenn man das mit einem Submodul eines Packages probiert, muss man sich das Environment entsprechend herrichten (z.B. indem man $PYTHONPATH passend setzt). Keine große Hexerei, wenn man es weiß, aber selbst dann vergisst man gerne darauf (ich zumindest). Ich würde daher davon abraten. hp

Am 04.05.24 um 13:12 schrieb Marc Haber:
Bei Pfadproblemen verwende ich sys.path.append( Hermann der das #include ../ich.h für gemeinsames vermisst. -- <http://www.hermann-riemann.de>

On Sun, May 05, 2024 at 12:02:34PM +0200, Hermann Riemann wrote:
Bei Pfadproblemen verwende ich sys.path.append(
In Klassen- und Moduldefinitionen und importen? Echt jetzt? Oder hast Du nur die Frage nicht verstanden? Grüße Marc -- ----------------------------------------------------------------------------- Marc Haber | "I don't trust Computers. They | Mailadresse im Header Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402 Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421

Am 04.05.24 um 13:12 schrieb Marc Haber:
Ein wenig lässt sich mit sys.path.append erreichen. Ich benutze das für meine Hilfsprogramme, die von mehreren Programme verwendet werden. -- <http://www.hermann-riemann.de>
participants (5)
-
Bastian Blank
-
Hartmut Goebel
-
Hermann Riemann
-
Marc Haber
-
Peter J. Holzer