import von mehreren *.pyd

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.
Antworten
kap25
User
Beiträge: 3
Registriert: Donnerstag 22. Dezember 2016, 11:44

Hallo Zusammen,
ich habe ein Packet von mehreren *.pyd Modulen die sich folgendermaßen gegenseitig importieren:

Code: Alles auswählen

#A.pyd
import A.b  #Datei A_b.pyd
import A.c  #Datei A_b.pyd
wobei "A.b" die Datei "A_b.pyd" ist usw.. Wenn ich in meinem Programm "A.pyd" importiere dann werden die Referenzen A_b.pyd nicht gefunden.
Hat jemand eine Idee wie ich das angehen kann? Am liebsten mit einer __init__.py. Aber wie?
BlackJack

@kap25: Also ich habe das Problem nicht verstanden. Wenn Du in einem Modul das `A` heisst ``import A.b`` zu stehen hast, dann wird versuchst aus diesem Modul A das Objekt mit dem Namen `b` zu importieren. Das sich im Modul `A` befinden muss. Aber dann braucht man es dort nicht zu importieren, denn es befindet sich dort ja bereits. Sofern der Import *nach* der Definition von `b` kommt. Sonst gibt es `b` zu dem Zeitpunkt ja noch nicht.

Kannst Du ein minimales, lauffähiges Beispiel von dem Problem zeigen?
kap25
User
Beiträge: 3
Registriert: Donnerstag 22. Dezember 2016, 11:44

ich glaube das sind Biblieotheken die aus einer anderen Sprache übersetzt wurden. Zur Laufzeit wurde das Problem mit "sitecustomize.py" und "sys.meta_path" gelöst. Hier der Code von "sitecustomize.py:

Code: Alles auswählen

import importlib.machinery
import os, sys

class IILoader(importlib.machinery.ExtensionFileLoader):
    def load_module(self, fullname):
        return super(IILoader, self).load_module(fullname)

automation_namespaces = []

class MetaPathHook():
    def __init__(self):
        self.path = list()
        ii_base_dir = os.getenv('II_LIB_PATH')
        self.path.append(ii_base_dir)
        automation_namespaces.append('A')

    def find_module(self, fullname, path):
        for namespace in automation_namespaces:
            namespace_dot = namespace + '.'
            if fullname == namespace or fullname.startswith(namespace_dot):
                return self
        return None

    def load_module(self, fullname):
        libname = fullname
        for namespace in automation_namespaces:
            namespace_dot = namespace + '.'
            namespace_dash = namespace + '_'
            if libname.startswith(namespace_dot):
                libname = fullname.replace(namespace_dot, namespace_dash, 1)
            module_ext = '.pyd'
            libname = libname + module_ext
            for p in self.path:
                lib = os.path.join(p, libname)
                if os.path.exists(lib):
                    loader = IILoader(fullname, lib)
                    module = loader.load_module(None)
                    module.__path__ = "IIPackagePath"
                    try:
                        module._handle_import(module)
                    except:
                        print("could not call _handle_import", module)
                    return module
        raise ImportError(fullname)

sys.meta_path.insert(0, MetaPathHook())
Wenn ich die Shell starte und 'import A' eingebe, dann funktioniert alles. Nur beim programieren in PyCharm funktioniert die Vervollständigung nicht. Weil bei der Erstellung von "Binary Skeletons" die imports nicht gefunden werden.
BlackJack

@kap25: Ich wüsste nicht was man da machen kann bzw. was Du da jetzt eigentlich machen *willst*. Da werden Module importiert die irgendwo liegen können und in ein einer Verzeichnisstruktur und mit Namen die nicht dem Standard entsprechen. Dazu gibt's Code der das dynamisch auf eine Package/Modulhierarchie bei Bedarf, also beim importieren, abbildet. Das lässt sich statisch nicht analysieren (solange man nur von Standardimportmechanismen ausgeht), also funktioniert eine Autovervollständigung nicht, ohne tatsächlich zu importieren.

Ich glaube Pycharm kennt irgendein Dateiformat in dem die Signaturen etc. gespeichert werden und mit dessen Hilfe man der IDE auch solche Informationen beibringen kann die sich nicht statisch ermitteln lassen, entweder wegen solcher dynamischen Importmechanismen oder weil sich die API nicht untersuchen lässt. (C-Erweiterungen müssen nicht alle Informationen liefern die man von reinen Python-Objekten abfragen kann.)

Du könntest also versuchen selbst Introspection-Code zu schreiben der solche Dateien erstellt.
kap25
User
Beiträge: 3
Registriert: Donnerstag 22. Dezember 2016, 11:44

ich habe gehofft, dass man in der __init__.py sowas wie: "A.b=__import__(A_b)" realisieren kann.
BlackJack

PyCharm verwendet „python skeletons“ um die Autovervollständigung zu verbessern. Das sind einfach Python-Dateien mit den entsprechenden Annotationen die statisch analysiert werden können: https://github.com/JetBrains/python-skeletons
Antworten