列出在其他地方部署工作项目所需的所有依赖项(比如在不同的操作系统上),最有效的方法是什么?
Python 2.7,Windows开发环境,不是每个项目使用virtualenv,而是全局开发环境,根据需要安装库,愉快地从一个项目跳到另一个项目。
我已经跟踪了我必须为给定项目安装的大多数(不确定所有)库。我不跟踪自动安装它们的任何子依赖项。执行pip freeze
会列出所有已安装的库以及所有其他库。
有没有办法列出您需要安装的内容,不多也不少,以便部署项目?
注意:无法想象这里已经没有Q + A,但我无法找到它。
编辑鉴于以下答案,请进行一些澄清。我的项目由一堆模块(我写的)组成,每个模块都有一堆import
个。我应该只是将所有模块中的所有导入复制粘贴到一个文件中,排序消除重复,并从标准库中丢弃所有(以及我怎么知道它们)?或者,还有更好的方法?这就是问题所在。
答案 0 :(得分:37)
pipreqs
解决了这个问题。它会生成 项目级 requirement.txt文件。
安装pipreqs:pip install pipreqs
pipreqs /path/to/your/project/
如果您希望了解pipreqs
超过pip freeze
的更多优势,请阅读from here
答案 1 :(得分:11)
扫描您的2.4.0 :007 > str = "A more"
=> "A more"
2.4.0 :009 > str.split(/^([ab])[[:space:]]+/i)
=> ["", "A", "more"]
声明。您可能只导入您明确要导入的内容,而不是依赖项。
制作一个像import
那样的列表,然后创建并激活virtualenv。
执行pip freeze
,并尝试在该virtualenv中运行您的代码。注意任何pip install -r your_list
例外情况,将它们与包匹配,然后添加到列表中。重复直到您的代码运行没有问题。
现在,您有一个列表可以提供给部署站点上的ImportError
。
这是非常手动的,但不需要外部工具,并强制您确保代码运行。 (运行测试套件作为检查很好,但还不够。)
答案 2 :(得分:1)
执行此操作的方法是分析您的导入。要自动执行此操作,请查看Snakefood。然后,您可以制作git push -f
文件并开始使用requirements.txt
。
以下将列出依赖项,不包括标准库中的模块:
virtualenv
相关问题:
答案 3 :(得分:1)
我发现这里的答案对我来说效果不佳,因为我只想要从我们的存储库内部导入(例如,import requests
我不需要,但 from my.module.x import y
我确实需要) .
我注意到 PyInstaller
对此具有非常好的功能。我做了一些挖掘并设法找到了他们的依赖图代码,然后只是创建了一个函数来通过一些反复试验来做我想做的事情。我做了一个 gist here,因为我将来可能会再次需要它,但代码如下:
import os
from PyInstaller.depend.analysis import initialize_modgraph
def get_import_dependencies(*scripts):
"""Get a list of all imports required.
Args: script filenames.
Returns: list of imports
"""
script_nodes = []
scripts = set(map(os.path.abspath, scripts))
# Process the scripts and build the map of imports
graph = initialize_modgraph()
for script in scripts:
graph.run_script(script)
for node in graph.nodes():
if node.filename in scripts:
script_nodes.append(node)
# Search the imports to find what is in use
dependency_nodes = set()
def search_dependencies(node):
for reference in graph.getReferences(node):
if reference not in dependency_nodes:
dependency_nodes.add(reference)
search_dependencies(reference)
for script_node in script_nodes:
search_dependencies(script_node)
return list(sorted(dependency_nodes))
if __name__ == '__main__':
# Show the PyInstaller imports used in this file
for node in get_import_dependencies(__file__):
if node.identifier.split('.')[0] == 'PyInstaller':
print(node)
所有节点类型都在PyInstaller.lib.modulegraph.modulegraph
中定义,例如SourceModule
、MissingModule
、Package
和BuiltinModule
。这些在执行检查时会很有用。
每一个都有一个 identifier
(path.to.my.module
),并且根据节点类型,它可能有一个 filename
(C:/path/to/my/module/__init__.py
) 和 {{1} } (packagepath
)。
我真的不能发布任何额外的代码,因为它非常特定于我们将 ['C:/path/to/my/module']
与 pyarmor
一起使用的设置,但我可以很高兴地说,到目前为止它可以完美运行。
答案 4 :(得分:0)
在您的终端上
pip安装pipdeptree
cd您的
pipdeptree
答案 5 :(得分:0)
我只会运行以下内容:
import importlib
import os
import pathlib
import re
import sys, chardet
from sty import fg
sys.setrecursionlimit(100000000)
dependenciesPaths = list()
dependenciesNames = list()
paths = sys.path
red = fg(255, 0, 0)
green = fg(0, 200, 0)
end = fg.rs
def main(path):
try:
print("Finding imports in '" + path + "':")
file = open(path)
contents = file.read()
wordArray = re.split(" |\n", contents)
currentList = list()
nextPaths = list()
skipWord = -1
for wordNumb in range(len(wordArray)):
word = wordArray[wordNumb]
if wordNumb == skipWord:
continue
elif word == "from":
currentList.append(wordArray[wordNumb + 1])
skipWord = wordNumb + 2
elif word == "import":
currentList.append(wordArray[wordNumb + 1])
currentList = set(currentList)
for i in currentList:
print(i)
print("Found imports in '" + path + "'")
print("Finding paths for imports in '" + path + "':")
currentList2 = currentList.copy()
currentList = list()
for i in currentList2:
if i in dependenciesNames:
print(i, "already found")
else:
dependenciesNames.append(i)
try:
fileInfo = importlib.machinery.PathFinder().find_spec(i)
print(fileInfo.origin)
dependenciesPaths.append(fileInfo.origin)
currentList.append(fileInfo.origin)
except AttributeError as e:
print(e)
print(i)
print(importlib.machinery.PathFinder().find_spec(i))
# print(red, "Odd noneType import called ", i, " in path ", path, end, sep='')
print("Found paths for imports in '" + path + "'")
for fileInfo in currentList:
main(fileInfo)
except Exception as e:
print(e)
if __name__ == "__main__":
# args
args = sys.argv
print(args)
if len(args) == 2:
p = args[1]
elif len(args) == 3:
p = args[1]
open(args[2], "a").close()
sys.stdout = open(args[2], "w")
else:
print('Usage')
print('PyDependencies <InputFile>')
print('PyDependencies <InputFile> <OutputFile')
sys.exit(2)
if not os.path.exists(p):
print(red, "Path '" + p + "' is not a real path", end, sep='')
elif os.path.isdir(p):
print(red, "Path '" + p + "' is a directory, not a file", end, sep='')
elif "".join(pathlib.Path(p).suffixes) != ".py":
print(red, "Path '" + p + "' is not a python file", end, sep='')
else:
print(green, "Path '" + p + "' is a valid python file", end, sep='')
main(p)
deps = set(dependenciesNames)
print(deps)
sys.exit()
答案 6 :(得分:0)
这个答案是为了帮助某人列出 Python 脚本本身的版本的所有依赖项。这将列出用户虚拟环境中的所有依赖项。
from pip._internal.operations import freeze
x = freeze.freeze()
for dependency in x:
print(dependency)
为此,您需要安装 pip
作为依赖项。使用以下命令安装pip依赖。
pip install pip
打印输出如下所示。
certifi==2020.12.5
chardet==4.0.0
idna==2.10
numpy==1.20.3
oauthlib==3.1.0
pandas==1.2.4
pip==21.1.2
python-dateutil==2.8.1
pytz==2021.1
requests==2.25.1
requests-oauthlib==1.3.0
setuptools==41.2.0
six==1.16.0
urllib3==1.26.4
答案 7 :(得分:0)
您可以简单地使用 pipreqs,安装它:
pip install pipreqs
然后,在文件目录中键入:pipreqs .
。
将为您创建一个名为 requirements 的文本文件,如下所示:
numpy==1.21.1
pytest==6.2.4
matplotlib==3.4.2
PySide2==5.15.2