我发现 Colab 预安装的库以及 AWS Sagemaker 预定义的内核都很方便,但是在收集
requirements.txt
文件时,这种便利变得非常烦人,因为我最终得到了许多我在项目中并未实际使用的库。我知道我可以一开始就创建一个虚拟的,但我想知道是否有办法避免它。
我最近发现了watermark,它部分解决了这个问题。尽管如此,要使这个解决方案完美契合,它仍然存在两个问题,我将在下面举例说明,并且您可以在 Colab 中轻松重现。
!pip install fastai --upgrade
!pip install voila
!jupyter serverextension enable voila --sys-prefix
!pip install watermark
from fastai.vision.all import *
from fastai.vision.widgets import *
%load_ext watermark
%watermark --iversion
fastai
和 voila
都不会出现在输出中,因为我没有运行 import fastai 并加载瞧作为扩展。
%watermark -p fastai
这将返回正确的输出,例如
fastai
但我希望能够自动生成,而不必手动检查丢失的包。
虽然这不是 IPython 魔法,但我编写了这个小 Python 脚本(您可以将其复制为单元格并运行)。
它的工作原理是查看导入的模块,将它们与 pip 安装的发行版中的模块交叉引用,然后根据该信息创建一个
requirements.txt
。
from pip._internal.utils.misc import get_installed_distributions
import sys
#import numpy as np # imported to test whether numpy shows up, which it does!
def get_imported_packages():
p = get_installed_distributions()
p = {package.key:package.version for package in p}
imported_modules = set(sys.modules.keys())
imported_modules.remove('pip')
modules = [(m, p[m]) for m in imported_modules if p.get(m, False)]
return modules
def generate_requirements(filepath:str, modules):
with open(filepath, 'w') as f:
for module, version in modules:
f.write(f"{module}=={version}")
generate_requirements('requirements.txt', get_imported_packages())
我在 Colab 中遇到了同样的问题,但我想出了一个非常简单的方法。
要获取没有主机依赖项的requirements.txt:
在安装之前,使用主机默认值保存基线 requirements.txt 文件:
pip freeze > /content/requirements_v0.txt
安装 pip 后,保存完整环境的 requirements.txt 文件:
pip freeze > /content/requirements_v1.txt
仅提取您的包:
requirements_before_installs = '/content/requirements_v0.txt'
requirements_after_installs = '/content/requirements_v1.txt'
'''
# filter out packages from junk
'''
with open(requirements_before_installs, 'r') as f:
junk = f.readlines()
with open(requirements_after_installs, 'r') as f:
packages_plus_junk = f.readlines()
packages = [package for package in packages_plus_junk if package not in junk]
'''
# save clean file
'''
output_filename = '/content/requirements_final.txt'
with open(output_filename, 'w') as f:
f.writelines(packages)