Menghentikan skrip PyQGIS yang memiliki loop tak terbatas, menggunakan keyboard?


12

Jadi saya menulis sebuah skrip yang melakukan apa yang saya inginkan berulang-ulang menggunakan "while True:" dalam interval waktu tertentu (setiap 5 detik menggunakan time.sleep (5)). Sejauh ini bagus, TAPI ketika saya ingin menghentikannya, saya tidak bisa.

Saya telah mencoba Control + C, Control + Break, Escape dan praktis mengabaikan keyboard saya. Satu-satunya cara untuk menghentikannya adalah dengan menutup QGIS. Ada ide? Selanjutnya, ketika skrip hits time.sleep (5) QGIS agak tertinggal dan membeku selama 5 detik dan saya tidak bisa, misalnya, menggeser lapisan tetapi saya menganggap ini normal.

Ini skrip saya:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import iface
import time


while True: 

    def change_color():
        active_layer = iface.activeLayer()
        pipeline=[]
        txt=open('C:/users/stelios/desktop/project/Sensor.txt','r')
        for line in txt.readlines():
            pipeline.append(line.split())
        print pipeline 
        pipeline2=[]
        for label,color in pipeline:
            if "0" in color:
                pipeline2.append([label,"green"])
            else:
                pipeline2.append([label,"red"])

        print pipeline2
        elatomatikoi=""
        categories=[]

        for label,color in pipeline2:
            if 'red' in color:
                elatomatikoi=elatomatikoi + label+","
            symbol = QgsSymbolV2.defaultSymbol(active_layer.geometryType())
            symbol.setColor(QColor(color))
            category = QgsRendererCategoryV2(int(label), symbol, label)
            categories.append(category)

        expression = 'id' 
        renderer = QgsCategorizedSymbolRendererV2(expression, categories)
        active_layer.setRendererV2(renderer)
        active_layer.setCacheImage(None)
        iface.mapCanvas().refresh()
        iface.legendInterface().refreshLayerSymbology(active_layer)
        elatomatikoi= elatomatikoi[:-1]

        for label,color in pipeline2:
            if 'red' in color:
                QMessageBox.critical(None,"Warning",("Leakage at pipe(s):%s\nCheck Pipeline status " %elatomatikoi))
                break
        txt.close()

    change_color()
    time.sleep(5)

Apa kondisi yang harus memicu 'keluar'?
Nickves

1
ada banyak cara untuk menerapkan proses tanpa pemblokiran dalam qgis. Anda mendapatkan kontrol tanpa menyerahkannya ke loop acara Qt. Saya sarankan untuk mengeksplorasi: 1) buat arsitektur berbasis-event atau 2) kelola proses Anda dalam subproses python atau cara sederhana) buat skrip Toolbox Pemrosesan dan jika perlu integrasikan dengan pilihan 2
Luigi Pirelli

3
Guys mungkin saya mengatakannya dengan cara yang salah. Biarkan saya ulangi pertanyaan dengan skenario baru: Anda membuka Python Console di QGIS, Anda mengetik: sementara 1: cetak "a" dan Anda menekan enter. Lalu ia mencetak 'a' selamanya. BAGAIMANA ANDA MENGHENTIKANNYA TANPA keluar QGIS? Itulah pertanyaan dan masalah sebenarnya
Stelios M

Ini mungkin lebih dari pertanyaan Python umum, jadi Anda mungkin lebih beruntung mendapat jawaban di StackOverflow.
Martin

@ Martin Akan lakukan. Tetapi ini adalah pertanyaan yang sangat kuat dan mengherankan saya bahwa kepala pengembang QGIS tidak memikirkan skenario loop tak terbatas dalam konsol python mereka. Jika Anda mengeksekusi ketika 1: mencetak 'a' di mesin Anda, apakah Anda dapat menghentikannya dengan keyboard atau itu salah sistem saya?
Stelios M

Jawaban:


2

QGIS menawarkan kekuatan penuh python untuk Anda. Ini membuka kemungkinan luar biasa tetapi juga dilengkapi dengan jebakan potensial. Yang mungkin membuat QGIS tidak responsif, membeku atau bahkan menabraknya. Gunakan dengan bijak!

Dalam kasus Anda, alih-alih mengirim utas ke mode tidur selama 5 detik, Anda lebih baik membiarkan QGIS melakukan sesuatu yang lain (seperti mendengarkan penekanan tombol atau penekanan tombol) dan memposting acara penghitung waktu ke loop acara utama yang akan mengembalikan kontrol ke skrip Anda 5 detik kemudian.

Anda dapat menggunakan contoh dari jawaban ini sebagai titik awal yang baik. Untuk menghentikannya, cukup sambungkan beberapa acara ke stop()slot timer.

def change_color():
    print('I am now red')

timer = QTimer()
timer.timeout.connect(change_color)
timer.start(5000)

someButton.clicked.connect(timer.stop)

Atau panggil saja secara manual dari konsol ketika Anda berpikir sudah waktunya untuk menghentikannya

timer.stop()

Anda juga dapat menginstal eventFilter () di jendela utama untuk mencegat penekanan tombol jika Anda membutuhkannya.


0

Saat bekerja, Anda dapat menggunakan widget QT dengan tombol batal.

Agak kasar, tapi ini skrip widget yang saya gunakan:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setupUi(self)
        self.running = True
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(100, 100)
        self.horizontalLayout_3 = QtGui.QHBoxLayout(Form)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.Cancel_btn = QtGui.QPushButton(Form)
        self.Cancel_btn.setMinimumSize(QtCore.QSize(0, 0))
        self.Cancel_btn.setMaximumSize(QtCore.QSize(425, 27))
        self.Cancel_btn.setObjectName(_fromUtf8("Cancel_btn"))
        self.horizontalLayout.addWidget(self.Cancel_btn)
        self.horizontalLayout_3.addLayout(self.horizontalLayout)
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Cancel", None))
        self.Cancel_btn.setText(_translate("Form", "Cancel", None))
        self.Cancel_btn.clicked.connect(self.Cancel)


    def Cancel(self):
        self.running = False

Ini dapat diimpor ke skrip pyQgis Anda (Anda harus menambahkan direktori ke sys.path) dan kemudian Anda dapat menggunakan variabel yang berjalan untuk menghentikan loop while Anda:

import sys
sys.path.append("path/to/cancel_widget")

import cancel_widget

btn = cancel_widget.Ui_Form()
btn.show()

while btn.running:
    ...
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.