Skip to content

子进程 (Subprocess) ​


在本食谱指南中,你将学习如何使用 Python 内置的 subprocess 模块在 Flet 应用中运行外部系统命令行工具。

当你需要与未通过 Flet API 直接暴露的底层操作系统平台工具或系统实用程序进行交互时,这种方法非常有用。

注意

当应用在浏览器中运行(Web 模式)时,不支持运行外部系统命令行工具。


使用示例 (Examples) ​

启动另一个 Android 应用 ​

有时,你的 Flet 应用可能需要打开另一个 Android 原生应用程序。例如,你可能想要打开“系统设置”应用,以便用户可以调整系统或应用的权限设置。

在 Android 上,这可以通过使用 am start 命令来完成,该命令会从 Android 系统的 shell 中启动特定的 Activity。

该命令需要指定目标 Activity 的组件名称(-n 参数),格式为:package.name/.ActivityName。

例如,Android “系统设置”应用使用的是: com.android.settings/.Settings

另外推荐在命令中传递 --user 标志。如果不带此标志,命令可能会失败并显示如下安全性权限报错:

text
Security exception: Permission Denial: startActivityAsUser asks to run as user -2 but is calling from uid u0a164; this requires android.permission.INTERACT_ACROSS_USERS_FULL

发生这种情况是因为 Android 可能会尝试为当前活动用户以外的其他多开用户运行启动该 Activity。设置 --user 0 可以确保该命令为系统的首要主要用户运行。

因此,完整的命令变成了: am start -n com.android.settings/.Settings --user 0

在 Flet 应用中可以实现如下:

python
import subprocess
import flet as ft

def main(page: ft.Page):
    def open_settings(e):
        result = subprocess.run(
            ["am", "start", "-n", "com.android.settings/.Settings", "--user", "0"],
            shell=False, # 默认为 False
            capture_output=True,
            text=True,
        )

        print("STDOUT:", result.stdout)
        print("STDERR:", result.stderr)

    page.add(
        ft.SafeArea(
            content=ft.Button("Open Settings app", on_click=open_settings)
        )
    )

ft.run(main)

在 Android 模拟器或物理设备上运行此应用,点击按钮时,你应该会看到系统的“设置”应用被成功拉起打开。


常见陷阱 (Common Pitfall) ​

当使用 subprocess.run() 时,请务必注意 shell 参数的使用方式。

以下写法将无法正常工作:

python
subprocess.run(
    ["am", "start", "-n", "com.android.settings/.Settings", "--user", "0"],
    shell=True
)

因为当设置了 shell=True 时,命令参数必须作为一整个单字符串传入,而不能是列表形式。

正确的用法为:

python
subprocess.run(
    "am start -n com.android.settings/.Settings --user 0",
    shell=True
)

然而,在可行的情况下,我们强烈建议首选 shell=False 配合参数列表的形式,如主示例中所示。这通常更为安全,并能规避由于 shell 语法解析机制所带来的各种潜在注入或解析错误问题。


关注我,学习大模型、大数据、Python等热门技术。