在 python 中解析 pip list / pip freeze 的输出

问题描述 投票:0回答:6

你好,我有一个这样的字符串:

AdvancedHTMLParser (8.0.1)\nappdirs (1.4.3)\nbeautifulsoup4 (4.6.0)\nchardet (3.0.4)\nchrome-gnome-shell (0.0.0)\ncupshelpers (1.0)\ncycler (0.10.0)\nCython (0.27.3)

我想将其拆分为元组列表。 这样每个列表项都有一个包含两个值的元组,即名称和版本(不带括号)。

我只能用换行符分割字符串,但我不知道如何正确获取括号中的数字等 有人可以解释一下我该怎么做吗?

编辑: 我正在尝试解析

pip list local

 def get_installed_modules(self):
    data = subprocess.check_output(["pip", "list", "--local"])
    result = [tuple(line.replace('(', '').replace(')', '').split())
              for line in data.splitlines()]
    print(result)

我有一个项目,我不能只分割字符串,但它需要一个像字节的对象......

TypeError: a bytes-like object is required, not 'str'
python list tuples
6个回答
7
投票

接受的答案不再适用于最新版本的 pip (> 10.0)

所有这些方法现在都在私有包中。 例如,冻结模块位于 _internal/operations 中。您仍然可以使用它,但我个人认为使用内部包不是一个好主意。它们可能会在新版本中轻松移动或更改。

你可以做的是继续使用 pip cli 版本,使用

--format json
选项格式化输出并在 python 中解析它。

 import subprocess
 import json
 data = subprocess.check_output(["pip", "list", "--format", "json"])
 parsed_results = json.loads(data)
 [(element["name"], element["version"]) for element in parsed_results]

3
投票

选项1
如果您从

pip
获得这些输出,您可以使用
pip.operations.freeze
-

以编程方式完成此操作
from pip.operations import freeze  

modules = list(
    map(lambda x: x.split('=='), freeze.freeze(local_only=True))
)

print(modules)

[['aiodns', '1.1.1'],
 ['aiohttp', '1.2.0'],
 ['appdirs', '1.4.0'],
 ['appnope', '0.1.0'],
 ['argparse', '1.4.0'],
...

选项2
您还可以使用

get_installed_distributions
,取自 here:

import pip

modules = []
for i in pip.utils.get_installed_distributions():
    modules.append((i.key, i.version))

print(modules)

[('pytreebank', '0.2.4'),
 ('cssselect', '1.0.1'),
 ('numba', '0.36.0.dev0+92.g2818dc9e2'),
 ('llvmlite', '0.0.0'),
 ('yarl', '0.8.1'),
 ('xlwt', '1.3.0'),
 ('xlrd', '1.1.0'),
 ...
]

选项3
第三种方法是使用

pip.main
-

import pip
pip.main(['list', 'local'])

但是,这会写入

stdout


2
投票

您还可以使用正则表达式:

>>> s = "AdvancedHTMLParser (8.0.1)\nappdirs (1.4.3)\nbeautifulsoup4 (4.6.0)\nchardet (3.0.4)\nchrome-gnome-shell (0.0.0)\ncupshelpers (1.0)\ncycler (0.10.0)\nCython (0.27.3)"
>>> re.findall(r"(.+) \((.+)\)", s)
[('AdvancedHTMLParser', '8.0.1'),
 ('appdirs', '1.4.3'),
 ('beautifulsoup4', '4.6.0'),
 ('chardet', '3.0.4'),
 ('chrome-gnome-shell', '0.0.0'),
 ('cupshelpers', '1.0'),
 ('cycler', '0.10.0'),
 ('Cython', '0.27.3')]

1
投票

直接说:

data = 'AdvancedHTMLParser (8.0.1)\nappdirs (1.4.3)\nbeautifulsoup4 (4.6.0)\nchardet (3.0.4)\nchrome-gnome-shell (0.0.0)\ncupshelpers (1.0)\ncycler (0.10.0)\nCython (0.27.3)'
result = [tuple(line.replace('(', '').replace(')', '').split())
          for line in data.splitlines()]

print(result)

输出:

[('AdvancedHTMLParser', '8.0.1'), ('appdirs', '1.4.3'), ('beautifulsoup4', '4.6.0'), ('chardet', '3.0.4'), ('chrome-gnome-shell', '0.0.0'), ('cupshelpers', '1.0'), ('cycler', '0.10.0'), ('Cython', '0.27.3')]

1
投票

拆分左括号上的每一行并删除右括号:

self.__all_modules = [tuple(x[:-1].split(" (")) for x in data.splitlines()]

0
投票

接受的答案仅适用于较旧的 pip 版本。在新版本中,必须按如下方式导入命令:

选项 1:

from pip._internal.operations import freeze

modules = list(map(lambda x: x.split("=="), freeze.freeze(local_only=True)))

print(modules)

[['aiodns', '1.1.1'],
 ['aiohttp', '1.2.0'],
 ['appdirs', '1.4.0'],
 ['appnope', '0.1.0'],
 ['argparse', '1.4.0'],

...

© www.soinside.com 2019 - 2024. All rights reserved.