检索Python解释器的命令行参数。

20

受到这里的另一个问题的启发,我想以一种便携的方式检索Python解释器的完整命令行。也就是说,我想获取解释器的原始argv,而不是排除解释器本身选项(如-m-O等)的sys.argv

sys.flags告诉我们设置了哪些布尔选项,但它不能告诉我们有关-m参数的信息,并且标志集随时间绑定会发生变化,从而增加了维护负担。

在Linux上,您可以使用procfs检索原始命令行,但这不是可移植的(而且有点恶心):

open('/proc/{}/cmdline'.format(os.getpid())).read().split('\0')

6
这是一个很好的问题...据我所知,在CPython中似乎不可能实现。在我的看法中,Py_Main 对命令行参数进行了一些解析,然后使用剩余的参数调用PySys_SetArgv,并且没有对*argc**argv做任何其他操作。虽然有Py_GetArgcArgv,但我没有在文档化的C-API中找到它的任何应用... - mgilson
1
.split('\0').replace('\0', ' ')更加正确--否则无法区分包含空格的参数和独立的参数。 - tripleee
2个回答

13

您可以使用ctypes

~$ python2 -B -R -u
Python 2.7.9 (default, Dec 11 2014, 04:42:00) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Persistent session history and tab completion are enabled.
>>> import ctypes
>>> argv = ctypes.POINTER(ctypes.c_char_p)()
>>> argc = ctypes.c_int()
>>> ctypes.pythonapi.Py_GetArgcArgv(ctypes.byref(argc), ctypes.byref(argv))
1227013240
>>> argc.value
4
>>> argv[0]
'python2'
>>> argv[1]
'-B'
>>> argv[2]
'-R'
>>> argv[3]
'-u'

1
这在Python 3.7中不再起作用。 >>> argv[0] 现在是 b'p' - szmoore

9

我会再添加一个答案。 @bav的答案适用于Python 2.7,但正如@szmoore所指出的那样,在Python 3中会出现问题(不仅限于3.7)。然而,下面的代码将在Python 2和Python 3中都有效(这是因为Python 3中的c_wchar_p而不是Python 2中的c_char_p),并且会正确地将argv转换为Python列表,以便在其他Python代码中使用时不会导致段错误:

def get_python_interpreter_arguments():
    argc = ctypes.c_int()
    argv = ctypes.POINTER(ctypes.c_wchar_p if sys.version_info >= (3, ) else ctypes.c_char_p)()
    ctypes.pythonapi.Py_GetArgcArgv(ctypes.byref(argc), ctypes.byref(argv))

    # Ctypes are weird. They can't be used in list comprehensions, you can't use `in` with them, and you can't
    # use a for-each loop on them. We have to do an old-school for-i loop.
    arguments = list()
    for i in range(argc.value - len(sys.argv) + 1):
        arguments.append(argv[i])

    return arguments

你会注意到它仅返回解释器参数,而排除了在 sys.argv 中找到的参数。您可以通过删除 - len(sys.argv) + 1 来消除这种行为。


你使用了哪个操作系统平台和解释器版本?在两次测试中,我都尝试过它,但程序崩溃了。我在Windows 10上使用Python 3.7进行了测试,并在Debian 9上使用Python 3.5进行了测试。 - JamesThomasMoon
1
以上代码可在Ubuntu 16.04和macOS 10.13上的Python 2.7、3.5、3.6和3.7上运行。我不使用Windows,所以无法在其上进行测试。我基本上认为,在Windows中,Python中所有与C相关的事情都完全不同(或者根本不起作用)。但是,这绝对可以跨越看似广泛的Unix范围工作。 - Nick Williams
1
@JamesThomasMoon 在我的电脑上工作,使用的是Ubuntu 20.04操作系统,Python版本为3.8.10和2.7.18。 - Lenormju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接