教學 7 - 啟動此(第三方)

到目前為止,我們建立的應用程式只使用了我們自己的程式碼,加上 BeeWare 提供的程式碼。但是,在現實應用程式中,您可能需要使用從 Python Package Index (PyPI) 下載的第三方程式庫。

讓我們修改我們的應用程式以包含第三方程式庫。

存取 API

應用程式需要執行的常見任務是在 Web API 上發出請求以檢索數據,並向使用者顯示該數據。這是一個玩具應用程序,因此我們沒有*真正的* API 可供使用,因此我們將使用 {JSON} Placeholder API 作為來源資料。

{JSON} Placeholder API 有許多``假``API 端點,您可以將其用作測試資料。這些 API 之一是``/posts/端點,它會傳回虛假的部落格文章。如果您在瀏覽器中開啟 ``https://jsonplaceholder.typicode.com/posts/42,您將獲得一個描述單一貼文的 JSON 有效負載 - 一些 Lorum ipsum ID 為42 的部落格文章的內容。

Python 標準函式庫包含存取 API 所需的所有工具。然而,內建的 API 等級非常低。它們是 HTTP 協定的良好實作 - 但它們要求使用者管理大量低階細節,例如 URL 重新導向、會話、驗證和有效負載編碼。作為``普通瀏覽器用戶``,您可能習慣於將這些詳細資訊視為理所當然,因為瀏覽器會為您管理這些詳細資訊。

因此,人們開發了第三方函式庫來包裝內建 API,並提供更簡單的 API,更適合日常瀏覽器體驗。我們將使用其中一個函式庫來存取 {JSON} Placeholder API - 一個名為 httpx 的函式庫。

讓我們為我們的應用程式新增一個``httpx`` API 呼叫。將導入新增至``app.py``頂部以導入``httpx``:

import httpx

然後修改``say_hello()``回調,使其看起來像這樣:

def say_hello(self, widget):
    with httpx.Client() as client:
        response = client.get("https://jsonplaceholder.typicode.com/posts/42")

    payload = response.json()

    self.main_window.info_dialog(
        greeting(self.name_input.value),
        payload["body"],
    )

這將更改``say_hello()``回調,以便在調用它時,它將:

  • 對 JSON 佔位符 API 發出 GET 請求以取得 post 42;

  • 將回應解碼為 JSON;

  • 擷取貼文內文;和

  • 包括該帖子的正文作為對話框的文字。

讓我們在公文包開發者模式下運行更新後的應用程序,以檢查我們的更改是否有效。

(beeware-venv) $ briefcase dev
Traceback (most recent call last):
File ".../venv/bin/briefcase", line 5, in <module>
    from briefcase.__main__ import main
File ".../venv/lib/python3.9/site-packages/briefcase/__main__.py", line 3, in <module>
    from .cmdline import parse_cmdline
File ".../venv/lib/python3.9/site-packages/briefcase/cmdline.py", line 6, in <module>
    from briefcase.commands import DevCommand, NewCommand, UpgradeCommand
File ".../venv/lib/python3.9/site-packages/briefcase/commands/__init__.py", line 1, in <module>
    from .build import BuildCommand  # noqa
File ".../venv/lib/python3.9/site-packages/briefcase/commands/build.py", line 5, in <module>
    from .base import BaseCommand, full_options
File ".../venv/lib/python3.9/site-packages/briefcase/commands/base.py", line 14, in <module>
    import httpx
ModuleNotFoundError: No module named 'httpx'

發生了什麼事?我們已將``httpx``新增至我們的*程式碼*中,但我們尚未將其新增至我們的開發虛擬環境。我們可以透過用``pip``安裝``httpx``來解決這個問題,然後重新執行``briefcase dev``:

(beeware-venv) $ python -m pip install httpx
(beeware-venv) $ briefcase dev

當您輸入名稱並按下按鈕時,您應該會看到一個類似以下內容的對話框:

Hello World 教學 7 對話框,在 macOS 上

我們現在有了一個可以使用的應用程序,使用第三方庫,在開發模式下運行!

運行更新的應用程式

讓我們將此更新的應用程式程式碼打包為獨立應用程式。由於我們已經更改了程式碼,因此我們需要遵循 教程 4 中的相同步驟:

更新打包應用程式中的程式碼:

(beeware-venv) $ briefcase update

[helloworld] Updating application code...
...

[helloworld] Application updated.

重建應用程式:

(beeware-venv) $ briefcase build

[helloworld] Adhoc signing app...
[helloworld] Built build/helloworld/macos/app/Hello World.app

最後,運行應用程式:

(beeware-venv) $ briefcase run

[helloworld] Starting app...
===========================================================================

但是,當應用程式運行時,您會在控制台中看到錯誤,以及崩潰對話框:

Hello World 教學 7 應用程式崩潰,在 macOS 上

再一次,應用程式無法啟動,因為``httpx``已安裝 - 但為什麼呢?我們不是已經安裝了``httpx``了嗎?

我們有 - 但僅限於開發環境。您的開發環境完全位於您的電腦本機 - 並且僅在您明確啟動它時才啟用。儘管Briefcase 有開發模式,但您使用Briefcase 的主要原因是打包您的程式碼,以便提供給其他人。

確保其他人擁有一個包含其所需一切的Python環境的唯一方法是建立一個完全隔離的Python環境。這意味著有一個完全隔離的 Python 安裝和一組完全隔離的依賴項。這就是當您執行``briefcase build``時,Briefcase 正在建置的內容—一個獨立的 Python 環境。這也解釋了為什麼未安裝``httpx`` - 它已安裝在您的*開發*環境中,但未安裝在打包的應用程式中。

因此 - 我們需要告訴 Briefcase 我們的應用程式具有外部相依性。

更新依賴項

在應用程式的根目錄中,有一個名為``pyproject.toml``的檔案。該檔案包含您最初執行``briefcase new``時提供的所有應用程式設定詳細資訊。

pyproject.toml 被分成幾個部分;其中一節描述了您的應用程式的設定::

[tool.briefcase.app.helloworld]
formal_name = "Hello World"
description = "A Tutorial app"
long_description = """More details about the app should go here.
"""
sources = ["src/helloworld"]
requires = []

requires 選項描述了我們應用程式的依賴關係。它是一個字串列表,指定您想要包含在應用程式中的庫(以及可選的版本)。

修改``requires``設置,使其顯示為:

requires = [
    "httpx",
]

透過添加此設置,我們告訴 Briefcase``當您建立我的應用程式時,在應用程式包中執行``pip install httpx````。任何可以作為``pip install``合法輸入的內容都可以在這裡使用 - 因此,您可以指定:

  • 特定的庫版本(例如``httpx==0.19.0``);

  • 一系列庫版本(例如``httpx>=0.19``);

  • git 儲存庫的路徑(例如,"git+https://github.com/encode/httpx");或者

  • 本機檔案路徑(但是 - 請注意:如果您將程式碼提供給其他人,則該路徑可能不會存在於他們的電腦上!)

在``pyproject.toml``中,您會注意到與作業系統相關的其他部分,例如``[tool.briefcase.app.helloworld.macOS]``和``[tool.briefcase.app.helloworld``.windows]`` 。這些部分*也*有一個``requires``設定。這些設定允許您定義其他特定於平台的依賴項 - 因此,例如,如果您需要特定於平台的庫來處理應用程式的某些方面,您可以在特定於平台的``requires``部分中指定該庫,並且該設定將僅用於該平台。您會注意到``toga``庫都是在特定於平台的``requires``部分中指定的 - 這是因為顯示使用者介面所需的庫是特定於平台的。

在我們的例子中,我們希望在所有平台上安裝``httpx``,因此我們使用應用程式層級``requires``設定。應用程式級相依性將始終被安裝;除了*應用程式層級的依賴項之外,還會安裝特定於平台的依賴項。

某些二進位套件可能不可用

在桌面平台(macOS、Windows、Linux)上,任何可安裝的``pip``都可以加入您的需求。在行動和網路平台上,您的選擇略有限制

簡而言之;任何 純Python 套件(即, 包含二進位模組的套件)都可以毫無困難地使用。但是,如果您的依賴項包含二進位元件,則必須對其進行編譯;目前,大多數Python套件不提供非桌面平台的編譯支援。

BeeWare 可以為一些流行的二進位模組(包括``numpy``、pandas``和``cryptography)提供二進位檔案。 通常 可以為行動平台編譯軟體包,但設定起來並不容易——這遠遠超出了像本教程這樣的介紹性教程的範圍。

現在我們已經告訴 Briefcase 我們的附加要求,我們可以嘗試再次打包我們的應用程式。確保您已將變更儲存到``pyproject.toml``,然後再次更新您的應用程式 - 這次傳入``-r``標誌。這告訴 Briefcase 更新打包應用程式中的要求:

(beeware-venv) $ briefcase update -r

[helloworld] Updating application code...
Installing src/hello_world...

[helloworld] Updating requirements...
Collecting httpx
  Using cached httpx-0.27.0-py3-none-any.whl.metadata (7.2 kB)
...
Installing collected packages: zipp, typing-extensions, travertino, sniffio, pycairo, idna, h11, exceptiongroup, certifi, pygobject, importlib-metadata, httpcore, anyio, toga-core, httpx, gbulb, toga-gtk
Successfully installed anyio-4.3.0 certifi-2024.2.2 exceptiongroup-1.2.1 gbulb-0.6.5 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 idna-3.7 importlib-metadata-7.1.0 pycairo-1.26.0 pygobject-3.48.2 sniffio-1.3.1 toga-core-0.4.4 toga-gtk-0.4.4 travertino-0.3.0 typing-extensions-4.11.0 zipp-3.18.1

[helloworld] Removing unneeded app content...
...

[helloworld] Application updated.

更新後,您可以運行``briefcase build``和``briefcase run`` - 您應該會看到打包的應用程序,具有新的對話框行為。

備註

用於更新需求的``-r``選項也受到``build``和``run``命令的支持,因此如果您想一步更新、構建和運行,您可以使用``briefcase``運行-u -r``。

下一步

我們現在有了一個使用第三方函式庫的應用程式!但是,您可能已經注意到,當您按下按鈕時,應用程式變得有點無響應。我們能做些什麼來解決這個問題嗎?前往 教學 8 找出…