首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与平台无关的功能

与平台无关的功能
EN

Code Review用户
提问于 2018-03-30 19:19:05
回答 3查看 1.2K关注 0票数 9

我正在尝试编写一个独立于平台的Python (>=3.6.5)包,其中包含一些需要使用javac编译和使用java运行的java .class文件。这是一个很简单的任务,但我需要知道用户是否已经安装了这些文件,以及假设它们都不在系统路径上的可执行文件的位置。这样,我就可以使用subprocess.run通过它的路径调用可执行文件。这给我带来了一个与平台无关的whereis命令。

代码语言:javascript
复制
import os, subprocess
from subprocess import CalledProcessError


def whereis(app):
    """Return a list of locations a given application.

    Relies on the `where` system command in Windows and the `whereis` command in Unix.

    Parameters
    ----------
    app : str
        Can be any application on the system path e.g. java.

    Returns
    -------
    result : list
        A list of locations where applications is installed.

    Useage
    ------
    >>>whereis('javac')
    'C:\\Program Files\\Java\\jdk1.8.0_162\\bin\\javac.exe'
    """

    result = None

    if os.name == "nt":# Windows
        try:
            result = subprocess.check_output("where {}".format(app))

        except CalledProcessError as err:
            print("Application ,",app,", not forund.",err)

    else:# Unix
        try:
            result = subprocess.check_output("whereis {}".format(app))

        except CalledProcessError as err:
            print("Application ,",app,", not found.",err)

    if result is None:
        print("")
        result = []
        return result

    else:
        result = result.decode().replace("\r", "").split("\n")
        result = list(filter(lambda x: len(x)>0, result))
        return result

问题

  1. 是否有一个标准的库函数已经涵盖了这一点?我找不到但这并不意味着什么。
  2. 我遗漏了什么警告或边缘案件吗?
  3. 可以对代码或docstring进行任何一般性改进吗?
EN

回答 3

Code Review用户

发布于 2018-03-30 22:06:27

小nit:

代码语言:javascript
复制
# Split this into individual lines - much easier to read
import os, subprocess

减少重复的代码和嵌套(同时也使用which) --这对于它所需要的内容来说太复杂了(我没有测试它):

代码语言:javascript
复制
def whereis(app):
    result = None

    command = 'where'
    if os.name != "nt":# Windows
        command = 'which'

    try:
        result = subprocess.check_output("{} {}".format(command, app))
    except CalledProcessError as err:
        print("Application ,",app,", not found.",err)

    if result is None:
        return []

    result = result.decode().splitlines()
    return [line for line in result if len(line)]
票数 4
EN

Code Review用户

发布于 2018-03-31 23:10:08

您可以使用一个三值条件运算符来确定每个操作系统的命令,使这个逻辑位为一个一行。除非对您的预期使用是必要的,否则我不认为返回空列表的意义,只要返回None,如果您的脚本什么也找不到。如果您在其他地方有一些代码看起来很像:

代码语言:javascript
复制
if not paths:
    # do something

如果paths是一个空列表,那么如果我们将它更改为None,它的工作方式将完全相同。

代码语言:javascript
复制
import os
import subprocess

def whereis(app):
    command = 'which' if os.name != 'nt' else 'where'
    try:
        result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
        return result.decode().split()
    except subprocess.CalledProcessError:
        return


if __name__ == '__main__':
    paths = whereis('notepad')

输出:

代码语言:javascript
复制
['C:\\Windows\\System32\\notepad.exe', 'C:\\Windows\\notepad.exe']
票数 3
EN

Code Review用户

发布于 2019-03-02 11:57:33

据我所知,您的代码对于空格或shell字符都是零转义,因此我假设它非常不安全,可以很容易地用于接管/ crash /.传递恶意输入时的整个应用程序。

您确实需要使用shlex.quote或类似的东西,或者使用which作为内置的非bash:subprocess.check_output(["which", your_argument])

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/190886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档