Opracowanie wtyczki zależnej od zewnętrznej biblioteki Python

29

Tworzę wtyczkę Python, celem jest zintegrowanie z QGIS funkcjonalności biblioteki Python PyPI o nazwie „elewacja”.

Czy istnieje niezależny od systemu operacyjnego sposób instalowania zewnętrznych bibliotek Python i udostępniania ich wtyczkom Python?

Znam już różne specyficzne dla systemu procedury instalowania zewnętrznej zależności Pythona. Chciałbym rozpowszechniać moją wtyczkę w różnych środowiskach, nie doprowadzając ludzi do szaleństwa.

Co ja już wiem

Przeszukując Internet i inne podobne pytania, wydaje się, że nie ma rozwiązania niezależnego od systemu operacyjnego.

Użytkownicy systemu Windows

Python jest pakowany i dystrybuowany w pakiecie QGIS, więc aby zainstalować zewnętrzne biblioteki Pythona, musisz przejść przez powłokę OSGeo4W i użyć stamtąd pip.

powiązane linki:

Użytkownicy OS X

W tym przypadku QGIS korzysta z wbudowanego Pythona, który jest wstępnie zapakowany w OS X i znajduje się w:

/usr/bin/python

Problem polega na tym, że domyślnie zainstalowany pip ma pewne ograniczenia i wymaga zbyt wielu uprawnień.

Szybkim obejściem jest użycie home-brew do zainstalowania Pythona, aby Twój pip mógł działać na modyfikowalnym przez użytkownika środowisku Python. Zobacz szczegóły tego podejścia tutaj .

Po zainstalowaniu wszystkich bibliotek Pythona przez pip, wystarczy dodać ich katalogi do zmiennej PATH.

Alternatywny sposób dla użytkowników OS X

Wewnątrz wtyczki kodu Python możesz użyć pip dostarczonego przez system, aby zainstalować wymagane pakiety. Następnie możesz sprawić, że właśnie zainstalowany pakiet będzie dostępny, dodając go do ścieżki.

import sys
import pip
pip.main(['install','--target=/Devel/test', 'elevation'])
sys.path.append("/Devel/test")

Domowe, ale działające rozwiązanie (przetestowane zarówno na systemie Linux, jak i OS X)

Zdecydowałem się na alternatywny sposób, ponieważ pozwala on na oddzielenie aktualizacji biblioteki i konserwacji od wtyczki. Za każdym razem, gdy nowy użytkownik instaluje wtyczkę, najnowsza wersja biblioteki elewacji jest bezpośrednio pobierana i instalowana przez pip w podkatalogu wtyczki.

self.plugin_dir = os.path.dirname(__file__)
self.elevation_dir = os.path.join(self.plugin_dir, 'elevation')

# Checking the presence of elevation library
try:
    import elevation
except:
    pip.main(['install', '--target=%s' % self.elevation_dir, 'elevation'])
    if self.elevation_dir not in sys.path:
        sys.path.append(self.elevation_dir)
Engineer-G
źródło
Ta procedura dotyczy tylko systemu Windows, ponieważ system operacyjny Unix (Linux, Mac OS X) korzysta ze standardowej zainstalowanej wersji Python
gen
Wiem, „wzbogacałem” moje pytanie, teraz jest sekcja użytkowników OS X, która wyjaśnia, jak to zrobić na komputerze Mac.
Engineer-G
1
Możesz idealnie zainstalować pip w Apple Python. QGIS używa tej wersji, a nie innych wersji (Homebrew, Anaconda i inne). Jeśli chcesz korzystać z Homebrew Python, musisz zainstalować wersję HomeGrew QGIS
gen
3
Jeśli jest to czysta biblioteka Pythona, możesz po prostu dystrybuować bibliotekę innej firmy ze swoją wtyczką jako podpakiet / moduł.
user2856

Odpowiedzi:

2

Wystąpił problem z uruchomieniem skryptów Python w QGIS, które zależą od zewnętrznej biblioteki Python. Najprostszym rozwiązaniem jest instalacja Boundless Desktop, który jest dostarczany z wierszem poleceń i instaluje własnego Pythona. Za pomocą wiersza poleceń można uruchomić i zainstalować (przy użyciu pip) dowolny zewnętrzny pakiet Pythona.

osmjit
źródło
1

Pracowałem nad tym trochę przy projekcie. Niestety nie ma naprawdę świetnego sposobu na osiągnięcie tego. Twoje rozwiązanie jest bardzo podobne do tego, co wymyśliłem, ale nie ma gwarancji, że użytkownik nawet zainstalował pip.

Skończyło się to na dołączeniu kopii pliku get_pip.py i użyciu polecenia execfile () w celu uruchomienia go w przypadku, gdy nie jest on dostępny.

Podobne do twojego ostatecznego rozwiązania:

self.plugin_dir = os.path.dirname(__file__)

try:
    import pip
except:
    execfile(os.path.join(self.plugin_dir, get_pip.py))
    import pip
    # just in case the included version is old
    pip.main(['install','--upgrade','pip'])

try:
    import somelibrary
except:
    pip.main(['install', 'somelibrary'])

Alternatywą byłoby oczywiście włączenie samej biblioteki do katalogu wtyczki. Ryzykujesz dostarczeniem starej wersji, ale teoretycznie nie będzie to miało znaczenia.

Jesse McMillan
źródło
1

To zadziałało dla mnie (w def run (self)):

    def load_libraries(self):
        import_path = os.path.join(self.plugin_dir, 'lib/python2.7/site-packages')
        sys.path.insert(0, import_path)

i konfiguracja virtualenv.

W przypadku systemu Windows wydaje się to jednak inna historia. Miałem problem z instalacją matplotlib.

geekdenz
źródło