So far, the application we have built only uses our own code, plus the code provided by BeeWare. However, in practice, you may want to use a third-party library downloaded from the Python package index (PyPI).
Let's modify our application to include third-party libraries.
Access API
A common task that an application needs to perform is to make a request on the Web API to retrieve data and display the data to the user. This is a toy application, so we don't have a real API to use, so we will use {JSON} Placeholder API as the data source.
The {JSON} placeholder API has many "fake" API endpoints that can be used as test data. One of these APIs is the / posts / endpoint, which returns fake blog posts. If you https://jsonplaceholder.typicode.com/posts/42 Open it in the browser and you will get some Lorum ipsum content describing the JSON payload of a single post - a blog post with ID 42.
The Python standard library contains all the tools needed to access the API. However, the level of built-in API is very low. They are good implementations of the HTTP protocol -- but they require users to manage many low-level details, such as URL redirection, session, authentication, and payload encoding. As a "normal browser user", you may be used to taking these details for granted because the browser will manage them for you.
Therefore, people have developed third-party libraries, which encapsulate the built-in API and provide a simpler API, which is closer to the daily browser experience. We will use one of these libraries to access the {JSON} Placeholder API - a library called httpx.
Let's add an httpx API call to our application. app.py add an import httpx at the top of to import:
import httpx
Then modify say_hello() callback to make it look like this:
def say_hello(self, widget): if self.name_input.value: name = self.name_input.value else: name = 'stranger' with httpx.Client() as client: response = client.get("https://jsonplaceholder.typicode.com/posts/42") payload = response.json() self.main_window.info_dialog( "Hello, {}".format(name), payload["body"], )
This will change say_hello() callback so that when it is called, it will:
Send a GET request on the JSON placeholder API to GET the post 42;
- Decode the response into JSON;
- Extract the body of the post; and
- Include the body of the post as the text of the dialog box.
Let's run our updated application in briefcase developer mode to check whether our changes are valid.
Apple system
(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'
Linux
(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'
window
(beeware-venv)C:\...>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'
What happened? We have added httpx to our code, but we haven't added it to our development virtual environment yet. We can solve this problem by installing httpx, pip, and then re running: briefcase dev
Apple system
(beeware-venv) $ python -m pip install httpx (beeware-venv) $ briefcase dev
Linux
(beeware-venv) $ python -m pip install httpx (beeware-venv) $ briefcase dev
window
(beeware-venv)C:\...>python -m pip install httpx (beeware-venv)C:\...>briefcase dev
When you enter a name and press the button, you should see a dialog box similar to the following:
Hello World tutorial 6 dialog box, on Windows
We now have a working application that uses a third-party library and runs in development mode!
Run updated applications
Let's package the updated application code into a separate application. Since we have made code changes, we need to follow the same steps in Tutorial 4:
Apple system
Update the code in the packaged application: (beeware-venv) $ briefcase update [hello-world] Updating application code... Installing src/hello_world... [hello-world] Application updated. Rebuild application: (beeware-venv) $ briefcase build [hello-world] Building AppImage... ... [hello-world] Built linux/Hello_World-0.0.1-x86_64.AppImage Finally, run the application: (beeware-venv) $ briefcase run [hello-world] Starting app... However, when the application is running, you will see a crash dialog box:
Linux
Update the code in the packaged application: (beeware-venv) $ briefcase update [hello-world] Updating application code... Installing src/hello_world... [hello-world] Application updated. Rebuild application: (beeware-venv) $ briefcase build [hello-world] Building AppImage... ... [hello-world] Built linux/Hello_World-0.0.1-x86_64.AppImage Finally, run the application: (beeware-venv) $ briefcase run [hello-world] Starting app... Traceback (most recent call last): File "/tmp/.mount_Hello_ifthSH/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/tmp/.mount_Hello_ifthSH/usr/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/tmp/.mount_Hello_ifthSH/usr/app/hello_world/__main__.py", line 1, in <module> from hello_world.app import main File "/tmp/.mount_Hello_ifthSH/usr/app/hello_world/app.py", line 8, in <module> import httpx ModuleNotFoundError: No module named 'httpx' Unable to start app hello-world.
window
Update the code in the packaged application: (beeware-venv)C:...>Briefcase update [hello-world] Updating application code... Installing src/hello_world... [hello-world] The application has been updated. Rebuild application: (beeware-venv)C:\...>briefcase build [hello-world] Built windows/msi/Hello World Finally, run the application: (beeware-venv)C:\...>briefcase run [hello-world] Starting app... Unable to start app hello-world.
Again, the application cannot start because httpx is installed - but why? Haven't we already installed httpx?
We have - but only the development environment. Your development environment is completely local to your machine - only enabled if you explicitly activate it. Although briefcases have a development model, the main reason you use briefcases is to package your code so that you can provide it to others.
The only way to ensure that others will have a python environment that contains everything they need is to build a completely isolated Python environment. This means a fully isolated Python installation and a set of fully isolated dependencies. This is what the briefcase is building at runtime -- an isolated Python environment. This also explains why it is not installed - it is installed in your development environment, but not in the packaged application. briefcase buildhttpx
So - we need to tell the briefcase that our application has an external dependency.
Update dependency
In the root directory of your application, there is a named pyproject toml. This file contains all the application configuration details that you provided at the initial run time. briefcase new
pyproject.toml is divided into several parts; One section describes the settings for your application:
[tool.briefcase.app.hello-world] formal_name = "Hello World" description = "A Tutorial app" icon = "src/hello_world/resources/hello-world" sources = ['src/hello_world'] requires = []
This requires option describes the dependencies of our application. It is a list of strings that specify the libraries (and optional versions) to include in the application.
Modify the requires setting to display:
requires = [ "httpx", ]
By adding this setting, we tell the Briefcase "when you build my application, run it into the application package". Any legal input can be used here - so you can specify: pip install httpxpip install
- Specific library version (for example, "httpx==0.19.0");
- A series of Library versions (for example, "httpx > = 0.19");
- Path to the GIT repository (for example, "git"+ https://github.com/encode/httpx "); or
- Local file path (but - please note: if you provide code to others, this path may not exist on their machine!)
Go down to pyproject Toml, you will notice other parts related to the operating system, such as [tool. Briefcase. App. Hello world. MacOS] and [tool. Briefcase. App. Hello world. Windows]. These sections also have a requires setting. These settings allow you to define other platform specific dependencies - for example, if you need a platform specific library to handle some aspects of the application, you can specify the library in the platform specific requirements section, and the setting will only be used for that platform. You will notice that these toga libraries are specified in the platform specific requirements section - this is because the libraries required to display the user interface are platform specific.
In our example, we want httpx to be installed on all platforms, so we use the application level requires setting. Application level dependencies will always be installed; In addition to application level dependencies, platform specific dependencies are installed.
- Use Python only on mobile devices (currently!)
- On desktop platforms (macOS, Windows, Linux), any PIP installable can be added to your requirements. On mobile platforms, your options are more limited -- you can only use pure Python packages, that is, packages that do not contain binary modules.
- This means that libraries such as numpy, scikit learn, or cryptography can be used in desktop applications, but not in mobile applications. This is mainly because mobile applications need binary modules compiled for multiple platforms, which is difficult to set.
- You can build a mobile Python application that uses binary modules, but it's not easy to set up -- far beyond the scope of introductory tutorials like this. This is an area we want to address - but it's not a simple task. If you want to add it to BeeWare, please consider supporting the project by becoming a member.
Now that we have told the briefcase about our additional dependencies, we can try packaging our application again. Make sure you have saved your changes to pyproject Toml, and then update your application again - this time by passing in the - d flag. This tells the briefcase to update the dependencies in the packaged application:
Apple system
(beeware-venv) $ briefcase update -d [hello-world] Updating dependencies... Collecting httpx Using cached httpx-0.19.0-py3-none-any.whl (77 kB) ... Installing collected packages: sniffio, idna, travertino, rfc3986, h11, anyio, toga-core, rubicon-objc, httpcore, charset-normalizer, certifi, toga-cocoa, httpx Successfully installed anyio-3.3.2 certifi-2021.10.8 charset-normalizer-2.0.6 h11-0.12.0 httpcore-0.13.7 httpx-0.19.0 idna-3.2 rfc3986-1.5.0 rubicon-objc-0.4.1 sniffio-1.2.0 toga-cocoa-0.3.0.dev28 toga-core-0.3.0.dev28 travertino-0.1.3 [hello-world] Updating application code... Installing src/hello_world... [hello-world] Application updated.
Linux
(beeware-venv) $ briefcase update -d [hello-world] Updating dependencies... Collecting httpx Using cached httpx-0.19.0-py3-none-any.whl (77 kB) ... Installing collected packages: sniffio, idna, travertino, rfc3986, h11, anyio, toga-core, rubicon-objc, httpcore, charset-normalizer, certifi, toga-cocoa, httpx Successfully installed anyio-3.3.2 certifi-2021.10.8 charset-normalizer-2.0.6 h11-0.12.0 httpcore-0.13.7 httpx-0.19.0 idna-3.2 rfc3986-1.5.0 rubicon-objc-0.4.1 sniffio-1.2.0 toga-cocoa-0.3.0.dev28 toga-core-0.3.0.dev28 travertino-0.1.3 [hello-world] Updating application code... Installing src/hello_world... [hello-world] Application updated.
window
(beeware-venv)C:\...>briefcase update -d [hello-world] Updating dependencies... Collecting httpx Using cached httpx-0.19.0-py3-none-any.whl (77 kB) ... Installing collected packages: sniffio, idna, travertino, rfc3986, h11, anyio, toga-core, rubicon-objc, httpcore, charset-normalizer, certifi, toga-cocoa, httpx Successfully installed anyio-3.3.2 certifi-2021.10.8 charset-normalizer-2.0.6 h11-0.12.0 httpcore-0.13.7 httpx-0.19.0 idna-3.2 rfc3986-1.5.0 rubicon-objc-0.4.1 sniffio-1.2.0 toga-cocoa-0.3.0.dev28 toga-core-0.3.0.dev28 travertino-0.1.3 [hello-world] Updating application code... Installing src/hello_world... [hello-world] Application updated.
After the update, you can run and - you should see the packaged application and the new dialog behavior. briefcase buildbriefcase run
next step
We now have an application that uses third-party libraries! However, you may have noticed that the application becomes a little slow when you press the button. What can we do to solve this problem? Go to tutorial 7 to learn