Mengapa urutan impor penting dalam skrip pemrosesan PyQGIS mandiri?

13

Saya telah menemukan masalah aneh saat menjalankan skrip pemrosesan PyQGIS mandiri. Urutan impor dalam skrip memengaruhi eksekusi normal.

Anda dapat mereproduksi masalah dengan membuka konsol Python dan memasukkan skrip berikut (saya menggunakan GNU / Linux, QGIS 2.6.1, memproses plugin v.2.2.0-2, dan Python 2.7.3):

# Prepare the environment
import sys
from qgis.core import QgsApplication
from PyQt4.QtGui import QApplication
app = QApplication([])
QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()

# Prepare processing framework 
sys.path.append('/home/YOUR_USER/.qgis2/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()

print Processing.getAlgorithm("qgis:creategrid")

# Exit applications
QgsApplication.exitQgis()
QApplication.exit()

Anda harus mendapatkan:

ALGORITHM: Create grid
    HSPACING <ParameterNumber>
    VSPACING <ParameterNumber>
    WIDTH <ParameterNumber>
    HEIGHT <ParameterNumber>
    CENTERX <ParameterNumber>
    CENTERY <ParameterNumber>
    GRIDTYPE <ParameterSelection>
    CRS <ParameterCrs>
    SAVENAME <OutputVector>

Di sisi lain, jika Anda mengganti urutan impor (baris 3 dan 4), dengan cara ini:

from PyQt4.QtGui import QApplication
from qgis.core import QgsApplication

skrip sekarang kembali ... None, karena algoritme tidak ditemukan.

Masalah ini menyiratkan bahwa Anda tidak dapat menjalankan pemrosesan algoritma dari QGIS jika Anda (kebetulan) menulis impor dengan urutan yang salah.

Saya sudah memeriksa di StackOverflow tetapi menurut Do Python import order order , ordernya tidak terlalu penting. Selain itu, Panduan Gaya untuk Kode Python memberitahu kita untuk mengimpor pustaka standar (lebih umum) terlebih dahulu, kemudian pustaka pihak ketiga terkait, dan akhirnya, impor khusus aplikasi lokal. Saya pikir PyQt4 terletak pada kategori impor ke-2, sedangkan PyQGIS akan spesifik untuk aplikasi lokal, jadi impor PyQt4 harus didahulukan (walaupun saya bukan ahli dalam hal ini).

Apakah Anda punya ide mengapa ini bisa terjadi? Pernahkah Anda mengalami hal serupa?


EDIT 1: Mengubah impor implisit ( from abc import *) oleh yang eksplisit (misalnya, from abc import xyz) seperti yang disarankan oleh @ mike-t.

Germán Carrillo
sumber
2
Hanya ingin mengatakan, pertanyaan luar biasa dengan contoh pendek yang dapat direproduksi dan bukti penelitian dan analisis penelitian itu.
user2856

Jawaban:

14

tl; dr

import qgis
import PyQt4
etc

adalah cara yang benar

Versi panjang

Ya, pesanan impor dapat berarti dan dalam kasus QGIS 2.0 dan di atasnya itu penting.

Anda harus selalu mengimpor qgis.coreatau qgis.gui, bahkan import qgissudah cukup, sebelum Anda mengimpor barang PyQt.

Itu tampak konyol. Mengapa?

Di QGIS 2.0 kami beralih menggunakan versi 2 binding SIP yang membuat API memanggil lebih banyak Python seperti misalnya itu akan secara otomatis mengkonversi tipe untuk Anda:

1.0 SIP yang harus Anda lakukan:

value.toString()

dalam 2.0

value

hanya akan bekerja jika itu adalah tipe string dalam kode C ++.

Ok jadi apa

Kicker adalah bahwa kita harus mengatur versi API ke 2 dalam kode sebelum mengatur sesuatu yang lain, Anda tidak dapat mengaturnya lagi setelah ditetapkan. Jika Anda mengimpor PyQt terlebih dahulu, ia akan menetapkan nilainya ke v1 tetapi semuanya di QGIS sekarang menggunakan v2. Untuk memperbaikinya, kita atur ke v2, qgis.__init__.pytetapi kita harus mengimpor qgisterlebih dahulu atau jika tidak, PyQt menang.

Karena semua plugin di QGIS 2.0 dan di atas sekarang menggunakan SIP v2 setiap panggilan SIP v1 akan menghasilkan kesalahan saat berjalan.

Nathan W
sumber
1
Terima kasih Nathan, saya tidak menyadari implikasi seperti itu. Saya ingin tahu apakah masalah ini didokumentasikan dengan baik untuk pengembang PyQGIS. Misalnya, ini menunjukkan bagaimana plugin seharusnya terlihat, dan tidak menyebutkan apa pun tentang impor. Saya kira masalah ini tidak memengaruhi plugin dengan cara yang sama memengaruhi aplikasi / skrip mandiri. (Saya akan membatalkan jawaban Anda dalam beberapa menit, saya sudah menghabiskan semua suara harian :)).
Germán Carrillo
Ya itu tidak mempengaruhi plugin karena kami mengimpor qgis di c ++ sebelum PyQt.
Nathan W
Aneh ... Saya mendapatkan "ImportError: Tidak ada modul bernama PyQt" saat menggunakan import PyQtwalaupun import qgisberfungsi. Bukannya itu mengganggu saya sampai-sampai saya perlu mengajukan pertanyaan baru, hanya ingin tahu apakah Anda tahu mengapa ini terjadi. Saya menggunakan Windows 7 dengan versi pemrosesan / python yang sama dengan @ gcarrillo.
Joseph
Saya salah ketik. Lihat edit.
Nathan W