【问题标题】:Python GUI to execute Bash/ksh environment and shell applications?Python GUI 来执行 Bash/ksh 环境和 shell 应用程序?
【发布时间】:2015-09-21 19:18:46
【问题描述】:

我一直在深入研究 Python 和 GUI 应用程序,并取得了相当大的进步。但是,我想就如何进行以下操作提供一些建议:

  • 我已经使用 python(2.6.6 - 由于它是遗留系统而无法升级系统)和显示多个按钮的 gtk 创建了一个 GUI 应用程序,例如应用 1、应用 2、应用 3
  • 当我单击一个按钮时,它会运行一个 bash shell 脚本。该脚本将设置一些必需的环境变量,然后执行另一个外部应用程序(使用这些环境变量)

示例:
1) 使用点击按钮 app1
2) GUI 然后启动app1.sh 设置环境变量
3) GUI 然后运行external_app1

# external_app1 是一个示例应用程序
# 这需要一些环境
# 启动前要设置的变量


示例app1.sh 内容:

#/bin/bash

export DIR=/some/location/
export LICENSE=/some/license/
export SOMEVAR='some value'


注意:由于环境的配置方式,它必须先启动 shell 脚本来设置环境等,然后再启动外部应用程序。 shell 脚本将被锁定,因此一旦我测试过它们,任何人都无法对其进行编辑。


所以我考虑过如何让 python GUI 执行此操作,到目前为止,我正在执行以下操作:

  • 当用户点击app1时,检查app1.sh是否可执行/可读,如果不是,返回错误
  • 创建另一个 helper 脚本,假设 helper1.sh 将包含 app1.sh 后跟 external_app1 命令,然后让 python 通过以下命令执行 helper1.sh 脚本:李>

subprocess.Popen(helper1.sh, shell=True, stdout=out, stderr=subprocess.PIPE, close_fds=True)


示例helper1.sh 内容:

#!/usr/bin/env bash

source app1.sh   # sets up env variables

if [ $? = 0 ]; then
    external_app &    # Runs the actual application in background
else
    echo "Error executing app1.sh" 2>/dev/stderr
fi


这样做是为了让帮助脚本在其自己的子 shell 中执行,这样我就可以运行多个环境设置/外部应用程序(app2、app3 等)。

所以我问:

  1. 有没有更好的或者更 Pythonic 的方式来做到这一点?有人可以指出我正确的方向吗?
  2. 在日志记录和错误处理方面,如何在不阻塞/冻结 GUI 的情况下有效地从帮助脚本(例如helper1.sh)捕获标准错误或标准输出?使用线程还是队列?


谢谢。

【问题讨论】:

标签: python linux bash shell user-interface


【解决方案1】:

据我了解,您正在尝试使用 n 一组环境变量执行外部命令,其中 n 由用户指定。它是一个 GUI 应用程序这一事实似乎与问题无关。如果我遗漏了什么,请纠正我。

您有多种选择:

使用自定义环境变量在 Python 中执行命令

您可以直接使用env argument to Popen()来设置环境变量,而不是将环境变量存储在单独的文件中:

如果env不是None,则必须是为新进程定义环境变量的映射;使用这些而不是继承当前进程的环境,这是默认行为。

因此,不要使用app1.shapp2.shapp3.sh 等,而是将您的环境变量集存储在 Python 中,并将它们添加到您传递给 Popen() 的环境中,如下所示:

env_vars = {
  1: {
    'DIR': '/some/location/',
    'LICENSE': '/some/license/'
    'SOMEVAR': 'some value'
  },
  2: ...
}

...

environ_copy = dict(os.environ)
environ_copy.update(env_vars[n])
subprocess.Popen('external_application', shell=True, env=environ_copy, ...)

使用包装脚本修改环境

如果您的环境变量必须存在于单独的、专用的 shell 脚本中,那么您的助手之类的就是您能做的最好的了。

不过,我们可以稍微清理一下:

#!/usr/bin/env bash

if source "$1"; then  # Set up env variables
    external_app      # Runs the actual application
else
    echo "Error executing $1" 2>/dev/stderr
    exit 1            # Return a non-zero exit status
fi

这使您可以将app1.sh 传递给脚本,而不是创建n 单独的帮助文件。目前尚不清楚您为什么要使用 & 将进程置于后台 - Popen 启动一个单独的进程,该进程不会阻止 Python 进程继续进行。使用subprocess.PIPE,您可以使用Popen.communicate() 取回进程的标准输出和标准错误。

完全避免设置环境变量

如果您可以控制external_process(即您编写了它,并且可以修改它),您最好将其更改为使用命令行参数,而不是环境变量。这样你就可以调用:

subprocess.Popen('external_command', '/some/location/', '/some/license/', 'some value')

并避免完全需要shell=True 或包装脚本。如果external_command 需要许多变量,那么使用--flags(例如--dir /some/location/)而不是位置参数可能会更好。大多数编程语言都有一个(或多个)参数处理库来简化此操作; Python为此提供了argparse

使用命令行参数而不是环境变量将使external_process 更加用户友好,尤其是对于您所描述的用例。我建议这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 2020-04-04
    • 1970-01-01
    • 2014-03-23
    相关资源
    最近更新 更多