2017-08-03 43 views
0

我有兩個腳本在分離時根據需要運行。一個是PyQt5 GUI應用程序的代碼,第二個是與this one非常相似的代碼,稍作修改即可轉換內容,以防有任何笑臉導致問題。Python 3.6.2 - 多個__init__;多個類同時運行

基本上,當我按下我的應用程序窗口中的某個按鈕時,我期望第二個代碼被運行。

不管我多麼努力地嘗試適應第二個代碼,它總會使我的應用程序(或Python)崩潰。我能夠得到的最遠的地方是,當我關閉主窗口後第二個代碼工作 - 然後它運行,並給我我想要的結果。

我懷疑它與__init__第二個代碼不愉快,從主窗口運行已經有另一個__init__? 正如你所看到的,我對Python的面向對象部分感到非常困惑,儘管無論我在過去幾天試圖自我教育的過程中有多難,我都無法將這兩個代碼放在一起。

我的應用程序:

#'all the necessary imports' 

class MainWindow(QWidget): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     self.text = QWebEngineView(self) 
     self.proc_btn = QPushButton('Proceed') 
     self.userUrl = QLineEdit(self) 
     self.labOne = QLabel(self) 
     self.labTwo = QLabel(self) 
     self.defUrl = 'default' 
     self.init_ui() 



    def init_ui(self): 
     v_layout = QVBoxLayout() 
     h_layout = QHBoxLayout() 

     h_layout.addWidget(self.proc_btn) 
     h_layout.addWidget(self.userUrl) 

     v_layout.addWidget(self.text) 
     v_layout.addWidget(self.labOne) 
     v_layout.addWidget(self.labTwo) 

     v_layout.addLayout(h_layout) 

     self.labOne.setText('URL: ') 
     self.labTwo.setText('<ENTER LINK PLEASE>') 
     self.userUrl.returnPressed.connect(self.linkPut) 
     self.proc_btn.clicked.connect(self.doStuff) 
     self.setLayout(v_layout) 
     self.setWindowTitle('Scrapper') 
     self.show() 



    def doStuff(self): 
     print('Doing stuff (expecting 2nd script to be ran)') 

    def linkPut(self): 
     newText = (self.userUrl.text()) 
     print('newText: ' + newText) 
     self.labTwo.setText(newText) 
     self.defUrl = newText 


app = QApplication(sys.argv) 
a_window = MainWindow() 
sys.exit(app.exec_()) 

腳本我需要實現:

#'all necessary imports' 
class Page(QWebEnginePage): 
    def __init__(self, url): 
     self.app = QApplication(sys.argv) 
     QWebEnginePage.__init__(self) 
     self.html = '' 
     self.loadFinished.connect(self._on_load_finished) 
     self.load(QUrl(url)) 
     self.app.exec_() 
     print('__init__ WORKS') 

    def _on_load_finished(self): 
     self.html = self.toHtml(self.Callable) 
     print('Load finished') 

    def Callable(self, html_str): 
     self.html = html_str 
     self.app.quit() 


_nonbmp = re.compile(r'[\U00010000-\U0010FFFF]') 


def _surrogatepair(match): 
    char = match.group() 
    assert ord(char) > 0xffff 
    encoded = char.encode('utf-16-le') 
    return (
     chr(int.from_bytes(encoded[:2], 'little')) + 
     chr(int.from_bytes(encoded[2:], 'little'))) 

def with_surrogates(text): 
    return _nonbmp.sub(_surrogatepair, text) 


def main(): 
    page = Page('https://somenicepage.com/') 
    soup = bs.BeautifulSoup(page.html, 'html.parser')) 
    longStrCoded = str(soup.find("img", {"class":"pictures"})) 
    longStr = with_surrogates(longStrCoded) 
    print('long str: ' + longStr) 
    extract = longStr.split('src="')[1].split('"')[0] 
    print(extract) 

if __name__ == '__main__': main() 
+0

'進口other_py_file'在文件的開始,然後'other_py_file.main()'要觸發它 –

+0

這個我已經試過了,崩潰,如果我我的應用程序中使用它,但如果我關閉應用程序,然後運行'other_py_file.main()'它工作。 – NumeroSMG

+0

你能比'它墜毀'更具體嗎 –

回答

0

的問題是,在這兩個文件,您正試圖創建的QApplication多個實例,這是不允許的結合。此外,QApplication類旨在封裝您的整個應用程序邏輯並負責事件處理等。您通常不應該像在Page.__init__內部那樣在其他類中創建內容。

通常,您將創建並開始接近程序入口點的QApplication。您在第一個代碼塊中正確執行此操作。

if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) # Instantiate application 
    window = MainWindow() # The rest of your program logic should flow from here 
    sys.exit(app.exec_()) # Start application event loop 

QtWebEngine異步性質複雜的事情一點點,因爲你的程序將不會等待頁面上移動到下一個指令之前加載。我相信人們在頁面類中啓動QApplication是一種快速而骯髒(或天真)的方式來強制程序等待頁面完成加載。在Python腳本中這可能沒有問題,其中Qt僅用於QtWebEngine評估動態網頁的能力,但對於真實的Qt應用程序來說是不好的做法。處理這個問題的正確方法是通過回調或Qt的信號和插槽系統。

根據您的原始類,這裏是一個版本,它使用回調來繼續處理html完全加載後。

class Page(QtWebEngineWidgets.QWebEnginePage): 

    def __init__(self, url): 
     super(Page, self).__init__() 
     self.url = QtCore.QUrl(url) 
     self.callback = None 
     self.html = '' 
     self.loadFinished.connect(self.on_load_finished) 

    def load_html(self, callback=None): 
     self.callback = callback 
     self.load(self.url) 

    def on_load_finished(self): 
     self.toHtml(self.on_html_ready) 

    def on_html_ready(self, html): 
     self.html = html 
     if self.callback: 
      self.callback(html) 

接下來,定義將處理加載頁面的回調。在這裏你可以放置你的main()函數的代碼。

def do_stuff(html): 
    soup = bs.BeautifulSoup(html, 'html.parser')) 
    longStrCoded = str(soup.find("img", {"class":"pictures"})) 
    longStr = with_surrogates(longStrCoded) 
    print('long str: ' + longStr) 
    extract = longStr.split('src="')[1].split('"')[0] 
    print(extract) 

然後最後,您會在MainWindow類中加載這樣的頁面。

def doStuff(self): 
    self.page = Page(self.userUrl.text()) 
    self.page.load_html(callback=do_stuff) 

請注意在這裏使用self。如果我們不將頁面實例存儲在類中,它將在完成加載之前被刪除,並且回調將永遠不會被調用。

+0

謝謝,不僅現在有效,而且這幫助我理解了很多。 – NumeroSMG