乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Python3快速入門(十八)

       大傻子的文淵閣 2020-03-25

      PyInstaller打包發(fā)布

      一、PyInstaller簡介

      1、PyInstaller簡介

      PyInstaller是一個跨平臺的Python應用打包工具,支持 Windows/Linux/MacOS三大主流平臺,能夠把 Python 腳本及其所在的 Python 解釋器打包成可執(zhí)行文件,從而允許最終用戶在無需安裝 Python 的情況下執(zhí)行應用程序。
      PyInstaller 制作出來的執(zhí)行文件并不是跨平臺的,如果需要為不同平臺打包,就要在相應平臺上運行PyInstaller進行打包。

      2、PyInstaller安裝

      pip install PyInstaller

      二、PyInstaller基礎用法

      1、PyInstaller使用

      pyinstaller main.py
      PyInstaller 最簡單使用只需要指定作為程序入口的腳本文件。PyInstaller 執(zhí)行打包程序后會在當前目錄下創(chuàng)建下列文件和目錄:
      main.spec 文件,其前綴和腳本名相同,指定了打包時所需的各種參數;
      build 子目錄,其中存放打包過程中生成的臨時文件。warnxxxx.txt文件記錄了生成過程中的警告/錯誤信息。如果 PyInstaller 運行有問題,需要檢查warnxxxx.txt文件來獲取錯誤的詳細內容。xref-xxxx.html文件輸出 PyInstaller 分析腳本得到的模塊依賴關系圖。
      dist子目錄,存放生成的最終文件。如果使用單文件模式將只有單個執(zhí)行文件;如果使用目錄模式的話,會有一個和腳本同名的子目錄,其內才是真正的可執(zhí)行文件以及附屬文件。

      2、PyInstaller命令行選項

      PyInstaller命令行選項可以通過幫助信息查看:
      pyinstaller --help
      -y | --noconfirm:直接覆蓋輸出文件,而無需提示,在多次重復運行命令時可避免反復確認。
      -D | --onedir:生成包含執(zhí)行文件的目錄(默認行為)。
      -F | --onefile:生成單一的可執(zhí)行文件,不推薦使用。
      -i | --icon [.ico | .exe | .icns]:為 Windows/Mac 平臺的執(zhí)行文件指定圖標。
      --version-file [filename]:添加文件版本信息。
      -c | --console | --nowindowed:通過控制臺窗口運行程序 并且分配標準輸入/輸出,(默認行為)。
      -w | --windowed | --noconsole:不創(chuàng)建控制臺窗口,也不分配標準輸入/輸出,主要用來運行 GUI 程序。沒有輸入輸出會給調試帶來一定困難,因此即便是 GUI 程序,建議在調試時禁用本選項,在最終發(fā)布時再打開。
      --add-data [file:dir]:添加數據文件。如果有多個文件需要添加,本選項可以出現多次。參數的格式為文件名+輸出目錄名,用路徑分隔符分割,在 Windows 下使用 ;,其它系統(tǒng)下則使用 :。 如果輸出到和腳本相同的目錄,則使用 . 作為輸出目錄。
      --add-binary [file:dir]:添加二進制文件,即運行程序所需的.exe/.dll/.so 等。

      3、單目錄模式

      單目錄模式是 PyInstaller 將 Python 程序編譯為同一個目錄下的多個文件,其中 xxxx.exe 是程序入口點(xxxx 是腳本文件名稱,可以通過命令行修改)。單目錄模式是 PyInstaller 的默認模式,可以自己加上 -D 或者 --onedir 開關顯式開啟。
      單目錄模式打包生成的目錄除可執(zhí)行文件外,還包括 Python 解釋器(PythonXX.dll)、系統(tǒng)運行庫(ucrtbase.dll 以及其它 apixx.dll),以及一些編譯后的 Python 模塊(.pyd 文件)。

      4、單文件模式

      單文件模式是將整個程序編譯為單一的可執(zhí)行文件。需要在命令行添加 -F 或者 --onefile 開關開啟。
      Python腳本是解釋型程序,而不是 原生的編譯程序,并不能產生出真正單一的可執(zhí)行文件。如果使用單文件模式,PyInstaller打包生成的是自動解壓程序,需要先把所有文件解壓到一個臨時目錄(通常名為_MEIxxxx,xxxx是隨機數字),再從臨時目錄加載解釋器和附屬文件。程序運行完畢后,如果一切正常,會將臨時目錄再刪除。
      PyInstaller會對運行時的Python解釋器修改。如果直接運行 Python 腳本,那么sys.frozen 變量不存在,如果通過 PyInstaller 生成的可執(zhí)行文件運行,PyInstaller 會設置sys.frozen 變量為 True;如果使用單文件模式,sys._MEIPASS 變量包含了PyInstaller 自動創(chuàng)建的臨時目錄名。
      單文件模式因為有臨時目錄和解壓文件過程,所以程序啟動速度會比較慢。如果程序運行到一半崩潰,則臨時目錄將沒有機會被刪除。

      三、PyInstaller規(guī)格文件

      PyInstaller 在生成文件的同時會創(chuàng)建一個相應的.spec 文件,.spec 文件本質上是一個特殊的 Python 腳本,記錄了生成所需的指令。

      1、Spec文件生成

      使用pyinstaller [options] xxx.py進行打包時,PyInstaller 會首先根據選項生成對應的 .spec 文件,然后執(zhí)行 .spec 文件所指定的過程生成最終文件。因此,可以直接指定spec文件執(zhí)行打包過程。
      pyinstaller [options] xxx.spec

      2、Spec文件格式

      單目錄模式生成的spec 文件格式如下:

      a = Analysis(...)
      pyz = PYZ(...)
      exe = EXE(...)
      coll = COLLECT(...)

      單文件模式生成的spec 文件格式如下:

      a = Analysis(...)
      pyz = PYZ(...)
      exe = EXE(...)

      單文件模式是將所有內容統(tǒng)一打包到 .exe,而單目錄模式除了生成 .exe 外,還需要拷貝其它附屬文件。
      Analysis用于分析腳本的引用關系,并將所有查找到的相關內容記錄在內部結構中,供后續(xù)步驟使用;
      PYZ將所有 Python 腳本模塊編譯為對應的 .pyd 并打包;
      EXE:將打包后的 Python 模塊及其它文件一起生成可執(zhí)行的文件結構;
      COLLECT:將引用到的附屬文件拷貝到生成目錄的對應位置。
      如果數據文件很多導致 Analysis 太長,則可以提取為單獨的變量。

      data_files = [(...)]
      a = Analysis(...,
                   datas=data_files,
                   ...)

      可以為數據/二進制文件指定通配符,從而匹配同一類型的多個文件。

      a = Analysis(...,
                   datas=[('media/*.mp3', 'media')],
                   ...)

      可以將指定文件和指定目錄打包進行打包,如下:

      a = Analysis(...,
                   datas=[('config.ini', '.'), ('data', 'data')],
                   ...)

      將config.ini文件打包當可執(zhí)行文件當前目錄下,將data目錄打包到可執(zhí)行文件當前目錄下。

      四、PyInstaller Hook機制

      1、PyInstaller Hook簡介

      PyInstaller 使用遞歸方法,從入口的腳本文件逐個分析,獲取依賴模塊。
      PyInstaller 能識別 ctypes、SWIG、Cython 等形式的模塊調用,但文件名必須為字面值。但PyInstaller 無法識別動態(tài)和調用,例如 import、exec、eval,以及以變量為參數的調用。
      當 PyInstaller 識別完所有模塊后,會在內部構成一個樹形結構表示調用關系圖,調用關系在生成目標時也會一并輸出(xref-xxxx.html 文件)。PYZ 步驟會將所有識別到的模塊匯集起來,如果有必要會編譯成.pyd,然后將文件打包。但仍然存在以下問題:
      (1)由于動態(tài)模塊調用未必可以自動識別到,因此不會打包到文件中,執(zhí)行時肯定會出現問。
      (2)有些模塊并非是以模塊的形式,而是通過文件系統(tǒng)去訪問 .py 文件,代碼在運行時同樣會出現問題。
      為了解決上述問題,PyInstaller引入了Hooks機制,對于兩種問題引入了兩種類型的 Hook。兩種 Hook 主要是按照加載時間區(qū)分,第一種Hook在 PyInstaller 文檔中沒有明確的命名,是在生成過程中,導入特定模塊時調用的,稱為 Import Hook;第二種是Runtime Hook,是在執(zhí)行文件啟動期間、加載特定模塊時調用的。

      2、Import Hooks

      PyInstaller 定義的所有 Hook 在 PyInstaller 安裝目錄的 hooks 子目錄下,文件的命名均為 hook-[模塊名].py 的形式,即為 Import Hook。
      當 PyInstaller 生成過程中找到特定的導入模塊,就會到hooks目錄下查找是否存在對應的Hook,如果存在,則執(zhí)行之。
      hook-PyQt5.py文件如下:

      import os
      
      from PyInstaller.utils.hooks import collect_system_data_files
      from PyInstaller.utils.hooks.qt import pyqt5_library_info, get_qt_binaries
      
      # Ensure PyQt5 is importable before adding info depending on it.
      if pyqt5_library_info.version:
          hiddenimports = [
              # PyQt5.10 and earlier uses sip in an separate package;
              'sip',
              # PyQt5.11 and later provides SIP in a private package. Support both.
              'PyQt5.sip'
          ]
      
          # Collect the ``qt.conf`` file.
          datas = [x for x in
                   collect_system_data_files(pyqt5_library_info.location['PrefixPath'],
                                             'PyQt5')
                   if os.path.basename(x[0]) == 'qt.conf']
      
          # Collect required Qt binaries.
          binaries = get_qt_binaries(pyqt5_library_info)

      hiddenimports是PyInstaller 用來描述并非通過 import 明確導入,而是通過其它動態(tài)機制加載的模塊。

      3、Runtime Hooks

      Runtime Hooks均位于 PyInstaller 安裝目錄下的loader\rthooks 子目錄下,并且命名方式是 pyi_rth_[模塊名稱].py(rth 代表 run time hook)。
      loader\rthooks.dat內容是一個字典,記錄了系統(tǒng)中所有支持的 Runtime Hooks。rthooks.dat文件如下:

      {
          'certifi':    ['pyi_rth_certifi.py'],
          'django':     ['pyi_rth_django.py'],
          'enchant':    ['pyi_rth_enchant.py'],
          'gi':         ['pyi_rth_gi.py'],
          'gi.repository.Gio':    ['pyi_rth_gio.py'],
          'gi.repository.GLib':   ['pyi_rth_glib.py'],
          'gi.repository.GdkPixbuf':    ['pyi_rth_gdkpixbuf.py'],
          'gi.repository.Gtk':    ['pyi_rth_gtk.py'],
          'gi.repository.Gst':    ['pyi_rth_gstreamer.py'],
          'gst':        ['pyi_rth_gstreamer.py'],
          'kivy':       ['pyi_rth_kivy.py'],
          'kivy.lib.gstplayer': ['pyi_rth_gstreamer.py'],
          'matplotlib': ['pyi_rth_mplconfig.py', 'pyi_rth_mpldata.py'],
          'osgeo':      ['pyi_rth_osgeo.py'],
          'pkg_resources':  ['pyi_rth_pkgres.py'],
          'PyQt4':      ['pyi_rth_qt4plugins.py'],
          'PyQt5':      ['pyi_rth_pyqt5.py'],
          'PyQt5.QtWebEngineWidgets': ['pyi_rth_pyqt5webengine.py'],
          'PySide':      ['pyi_rth_qt4plugins.py'],
          'PySide2':      ['pyi_rth_pyside2.py'],
          'PySide2.QtWebEngineWidgets': ['pyi_rth_pyside2webengine.py'],
          '_tkinter':    ['pyi_rth__tkinter.py'],
          'traitlets':  ['pyi_rth_traitlets.py'],
          'twisted.internet.reactor':        ['pyi_rth_twisted.py'],
          'usb':        ['pyi_rth_usb.py'],
          'win32com':   ['pyi_rth_win32comgenpy.py'],
          'multiprocessing': ['pyi_rth_multiprocessing.py'],
          'nltk': ['pyi_rth_nltk.py'],
      }

      Runtime Hooks 是在執(zhí)行文件運行期間執(zhí)行的。PyInstaller 修改了模塊加載機制,當運行期間加載任何模塊時,PyInstaller 會檢查是否有對應的 Runtime Hook,如果有,則運行相應Hook。因此,Runtime Hooks 是和腳本一起編譯到可執(zhí)行文件中的。
      pyi_rth_pyqt5.py文件如下:

      import os
      import sys
      
      # The path to Qt's components may not default to the wheel layout for
      # self-compiled PyQt5 installations. Mandate the wheel layout. See
      # ``utils/hooks/qt.py`` for more details.
      pyqt_path = os.path.join(sys._MEIPASS, 'PyQt5', 'Qt')
      os.environ['QT_PLUGIN_PATH'] = os.path.join(pyqt_path, 'plugins')
      os.environ['QML2_IMPORT_PATH'] = os.path.join(pyqt_path, 'qml')

      五、錯誤調試

      使用PyInstaller進行打包時,最常見的錯誤是Failed to execute script xxx,通常做法是先使用pyinstaller -c xxx.py將應用打包為控制臺應用,在命令行執(zhí)行相應可執(zhí)行程序查看錯誤輸出,進而逐個排除錯誤。

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多