qwebview in pyside after packaged with pyinstaller

2019-08-10 15:19发布

问题:

Here's my code

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *

from encodings import *
from codecs import *

class BrowserWindow( QWidget ):
    def __init__( self, parent=None ):
        QWidget.__init__( self, parent )

        self.Setup()
        self.SetupEvent()

    def Setup( self ):
        self.setWindowTitle( u"Truease Speedy Browser" )

        self.addr_input = QLineEdit()
        self.addr_go = QPushButton( "GO" )

        self.addr_bar = QHBoxLayout()
        self.addr_bar.addWidget( self.addr_input )
        self.addr_bar.addWidget( self.addr_go )


        for attr in [
                QWebSettings.AutoLoadImages,
                QWebSettings.JavascriptEnabled,
                QWebSettings.JavaEnabled,
                QWebSettings.PluginsEnabled,
                QWebSettings.JavascriptCanOpenWindows,
                QWebSettings.JavascriptCanAccessClipboard,
                QWebSettings.DeveloperExtrasEnabled,
                QWebSettings.SpatialNavigationEnabled,
                QWebSettings.OfflineStorageDatabaseEnabled,
                QWebSettings.OfflineWebApplicationCacheEnabled,
                QWebSettings.LocalStorageEnabled,
                QWebSettings.LocalStorageDatabaseEnabled,
                QWebSettings.LocalContentCanAccessRemoteUrls,
                QWebSettings.LocalContentCanAccessFileUrls,
            ]:
            QWebSettings.globalSettings().setAttribute( attr, True )

        self.web_view = QWebView()
        self.web_view.load( "http://www.baidu.com" )

        layout = QVBoxLayout()
        layout.addLayout( self.addr_bar )
        layout.addWidget( self.web_view )

        self.setLayout( layout )

    def SetupEvent( self ):
        self.connect(
            self.addr_input,
            SIGNAL("editingFinished()"),
            self,
            SLOT("Load()"),
            )
        self.connect(
            self.addr_go,
            SIGNAL("pressed()"),
            self,
            SLOT("Load()")
            )
        self.connect(
            self.web_view,
            SIGNAL("urlChanged(const QUrl&)"),
            self,
            SLOT("SetURL()"),
            )

    def Load( self, *args, **kwargs ):
        url = self.GetCleanedURL()
        if url != self.CurrentURL():
            self.web_view.load( url )

    def SetURL( self, *args, **kwargs ):
        self.addr_input.setText( self.CurrentURL() )

    def GetCleanedURL( self ):
        url = self.addr_input.text().strip()
        if not url.startswith("http"):
            url = "http://" + url
        return url

    def CurrentURL( self ):
        url = self.web_view.url().toString()
        return url

def Main():
    app = QApplication( sys.argv )
    widget = BrowserWindow()
    widget.show()
    return app.exec_()


if __name__ == '__main__':
    sys.exit( Main() )

I works well when i using python browser.py. but it goes wrong after packaged with pyinstaller -w browser.py.

  1. it doesn't load images
  2. can only display correct text in utf-8

And this is the pyinstaller output:

E:\true\wuk\app2>pyinstaller -w b.py
16 INFO: wrote E:\true\wuk\app2\b.spec
16 INFO: Testing for ability to set icons, version resources...
32 INFO: ... resource update available
32 INFO: UPX is not available.
46 INFO: Processing hook hook-os
141 INFO: Processing hook hook-time
157 INFO: Processing hook hook-cPickle
218 INFO: Processing hook hook-_sre
312 INFO: Processing hook hook-cStringIO
407 INFO: Processing hook hook-encodings
421 INFO: Processing hook hook-codecs
750 INFO: Processing hook hook-httplib
750 INFO: Processing hook hook-email
843 INFO: Processing hook hook-email.message
1046 WARNING: library python%s%s required via ctypes not found
1171 INFO: Extending PYTHONPATH with E:\true\wuk\app2
1171 INFO: checking Analysis
1171 INFO: building because b.py changed
1171 INFO: running Analysis out00-Analysis.toc
1171 INFO: Adding Microsoft.VC90.CRT to dependent assemblies of final executable
1171 INFO: Searching for assembly x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww ...
1171 INFO: Found manifest C:\WINDOWS\WinSxS\Manifests\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest
1187 INFO: Searching for file msvcr90.dll
1187 INFO: Found file C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375\msvcr90.dll
1187 INFO: Searching for file msvcp90.dll
1187 INFO: Found file C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375\msvcp90.dll
1187 INFO: Searching for file msvcm90.dll
1187 INFO: Found file C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375\msvcm90.dll
1266 INFO: Analyzing D:\Applications\Python\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\_pyi_bootstrap.py
1266 INFO: Processing hook hook-os
1282 INFO: Processing hook hook-site
1296 INFO: Processing hook hook-encodings
1391 INFO: Processing hook hook-time
1407 INFO: Processing hook hook-cPickle
1468 INFO: Processing hook hook-_sre
1578 INFO: Processing hook hook-cStringIO
1671 INFO: Processing hook hook-codecs
2016 INFO: Processing hook hook-httplib
2016 INFO: Processing hook hook-email
2109 INFO: Processing hook hook-email.message
2312 WARNING: library python%s%s required via ctypes not found
2468 INFO: Processing hook hook-pydoc
2516 INFO: Analyzing D:\Applications\Python\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\pyi_importers.py
2609 INFO: Analyzing D:\Applications\Python\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\pyi_archive.py
2687 INFO: Analyzing D:\Applications\Python\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\pyi_carchive.py
2782 INFO: Analyzing D:\Applications\Python\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\pyi_os_path.py
2782 INFO: Analyzing b.py
2796 INFO: Processing hook hook-PySide
2875 INFO: Hidden import 'codecs' has been found otherwise
2875 INFO: Hidden import 'encodings' has been found otherwise
2875 INFO: Looking for run-time hooks
7766 INFO: Using Python library C:\WINDOWS\system32\python27.dll
7796 INFO: E:\true\wuk\app2\build\b\out00-Analysis.toc no change!
7796 INFO: checking PYZ
7812 INFO: checking PKG
7812 INFO: building because E:\true\wuk\app2\build\b\b.exe.manifest changed
7812 INFO: building PKG (CArchive) out00-PKG.pkg
7828 INFO: checking EXE
7843 INFO: rebuilding out00-EXE.toc because pkg is more recent
7843 INFO: building EXE from out00-EXE.toc
7843 INFO: Appending archive to EXE E:\true\wuk\app2\build\b\b.exe
7843 INFO: checking COLLECT
7843 INFO: building COLLECT out00-COLLECT.toc

Use pyinstaller browser.py, and in the console window i got

QFont::setPixelSize: Pixel size <= 0 (0)
QSslSocket: cannot call unresolved function SSLv23_client_method
QSslSocket: cannot call unresolved function SSL_CTX_new
QSslSocket: cannot call unresolved function SSL_library_init
QSslSocket: cannot call unresolved function ERR_get_error
QSslSocket: cannot call unresolved function SSLv23_client_method
QSslSocket: cannot call unresolved function SSL_CTX_new
QSslSocket: cannot call unresolved function SSL_library_init
QSslSocket: cannot call unresolved function ERR_get_error
QSslSocket: cannot call unresolved function SSLv23_client_method
QSslSocket: cannot call unresolved function SSL_CTX_new
QSslSocket: cannot call unresolved function SSL_library_init
QSslSocket: cannot call unresolved function ERR_get_error
QSslSocket: cannot call unresolved function SSLv23_client_method
QSslSocket: cannot call unresolved function SSL_CTX_new
QSslSocket: cannot call unresolved function SSL_library_init
QSslSocket: cannot call unresolved function ERR_get_error
QFont::setPixelSize: Pixel size <= 0 (0)

回答1:

I encountered this same problem. It is caused by PyInstaller using incorrect versions of ssleay32.dll and libeay32.dll.

To fix, download and install "Win32 OpenSSL v1.0.1e".

Then create a spec file for your PyInstaller project:

pyi-makespec browser.py

Open your spec file, named browser.spec, and below the a = Analysis(['browser.py']) line, add:

for d in range(len(a.binaries)):
    if a.binaries[d][0].lower() == 'ssleay32.dll':
        print a.binaries[d]
        a.binaries[d] = ('ssleay32.dll', 'C:\\\OpenSSL-Win32\\ssleay32.dll', 'BINARY')
    if a.binaries[d][0].lower() == 'libeay32.dll':
        print a.binaries[d]
        a.binaries[d] = ('libeay32.dll', 'C:\\OpenSSL-Win32\\libeay32.dll', 'BINARY')

This will tell PyInstaller to use the OpenSSL-Win32 dlls instead of the ones your Python installation is using.

When running the Python script, my Python installation preferred the DLLs in my system path to those installed by pyOpenSSL/egenix, but when bundling with PyInstaller, it seems to prefer the pyOpenSSL/egenix ones. This should fix that.