torch.package¶
torch.package
添加了对创建包含构件和任意的包的支持
PyTorch 代码。这些包可以保存、共享、用于加载和执行模型
在以后或在其他计算机上部署,甚至可以使用 .torch::deploy
本文档包含教程、操作指南、说明和 API 参考,其中
将帮助您了解有关和如何使用它的更多信息。torch.package
警告
此模块依赖于不安全的模块。仅解包您信任的数据。pickle
可以构造恶意的 pickle 数据,这些数据将在解封期间执行任意代码。 切勿解压缩可能来自不受信任的来源或可能已被篡改的数据。
有关更多信息,请查看该模块的文档。pickle
我该如何...¶
查看包内有什么?¶
将包视为 ZIP 存档¶
a 的容器格式为 ZIP,因此任何使用标准 ZIP 文件的工具都应该
用于探索内容。与 ZIP 文件交互的一些常见方法:torch.package
unzip my_package.pt
将压缩文件解压缩到磁盘,您可以在其中自由检查其内容。torch.package
$ unzip my_package.pt && tree my_package
my_package
├── .data
│ ├── 94304870911616.storage
│ ├── 94304900784016.storage
│ ├── extern_modules
│ └── version
├── models
│ └── model_1.pkl
└── torchvision
└── models
├── resnet.py
└── utils.py
~ cd my_package && cat torchvision/models/resnet.py
...
Python 模块提供了一种读取和写入 ZIP 存档内容的标准方法。
zipfile
from zipfile import ZipFile
with ZipFile("my_package.pt") as myzip:
file_bytes = myzip.read("torchvision/models/resnet.py")
# edit file_bytes in some way
myzip.writestr("torchvision/models/resnet.py", new_file_bytes)
vim 具有本机读取 ZIP 存档的能力。您甚至可以编辑文件并 : 将它们返回存档中!
write
# add this to your .vimrc to treat `*.pt` files as zip files
au BufReadCmd *.pt call zip#Browse(expand("<amatch>"))
~ vi my_package.pt
使用 APIfile_structure()
¶
提供了一个方法,该方法将返回一个 Printable
和 queryable
对象。该
对象是一个简单的目录结构,可用于浏览
的当前内容。
file_structure()
torch.package
对象本身是可直接打印的,并将打印出文件树表示形式。要过滤返回的内容,
使用 glob-style 和 filtering 参数。
include
exclude
with PackageExporter('my_package.pt') as pe:
pe.save_pickle('models', 'model_1.pkl', mod)
importer = PackageImporter('my_package.pt')
# can limit printed items with include/exclude args
print(importer.file_structure(include=["**/utils.py", "**/*.pkl"], exclude="**/*.storage"))
print(importer.file_structure()) # will print out all files
输出:
# filtered with glob pattern:
# include=["**/utils.py", "**/*.pkl"], exclude="**/*.storage"
─── my_package.pt
├── models
│ └── model_1.pkl
└── torchvision
└── models
└── utils.py
# all files
─── my_package.pt
├── .data
│ ├── 94304870911616.storage
│ ├── 94304900784016.storage
│ ├── extern_modules
│ └── version
├── models
│ └── model_1.pkl
└── torchvision
└── models
├── resnet.py
└── utils.py
importer_file_structure = importer.file_structure()
found: bool = importer_file_structure.has_file("package_a/subpackage.py")
了解为什么将给定模块作为依赖项包含在内?¶
假设有一个给定的 module ,你想知道为什么你要作为一个依赖项拉入。
foo
foo
如果您想了解给定模块如何依赖于 ,该方法将
返回一个 DOT 格式的图形,其中显示 和 之间的所有依赖关系路径。
src
foo
src
foo
在我的包中包含任意资源并在以后访问它们?¶
公开了三种方法,这些方法允许您将
Python 对象、文本和二进制数据添加到包中。
save_pickle
save_text
save_binary
with torch.PackageExporter("package.pt") as exporter:
# Pickles the object and saves to `my_resources/tensor.pkl` in the archive.
exporter.save_pickle("my_resources", "tensor.pkl", torch.randn(4))
exporter.save_text("config_stuff", "words.txt", "a sample string")
exporter.save_binary("raw_data", "binary", my_bytes)
公开名为 的补充方法,并且允许您加载
来自包的 Python 对象、文本和二进制数据。
load_pickle
load_text
load_binary
importer = torch.PackageImporter("package.pt")
my_tensor = importer.load_pickle("my_resources", "tensor.pkl")
text = importer.load_text("config_stuff", "words.txt")
binary = importer.load_binary("raw_data", "binary")
自定义类的打包方式?¶
torch.package
允许自定义类的打包方式。通过在类上定义方法并定义相应的解包函数来访问此行为。这类似于为
Python 的正常 pickling 过程。__reduce_package__
__reduce__
步骤:
在 target 类上定义方法。此方法应将类实例保存在包内,并应返回相应解包函数的元组,其中包含调用解包函数所需的参数。当遇到目标类的实例时,将调用此方法。
__reduce_package__(self, exporter: PackageExporter)
PackageExporter
为类定义一个解包函数。此解包函数应执行重新构造和返回类实例的工作。函数签名的第一个参数应为实例,其余参数为用户定义。
PackageImporter
# foo.py [Example of customizing how class Foo is packaged]
from torch.package import PackageExporter, PackageImporter
import time
class Foo:
def __init__(self, my_string: str):
super().__init__()
self.my_string = my_string
self.time_imported = 0
self.time_exported = 0
def __reduce_package__(self, exporter: PackageExporter):
"""
Called by ``torch.package.PackageExporter``'s Pickler's ``persistent_id`` when
saving an instance of this object. This method should do the work to save this
object inside of the ``torch.package`` archive.
Returns function w/ arguments to load the object from a
``torch.package.PackageImporter``'s Pickler's ``persistent_load`` function.
"""
# use this pattern to ensure no naming conflicts with normal dependencies,
# anything saved under this module name shouldn't conflict with other
# items in the package
generated_module_name = f"foo-generated._{exporter.get_unique_id()}"
exporter.save_text(
generated_module_name,
"foo.txt",
self.my_string + ", with exporter modification!",
)
time_exported = time.clock_gettime(1)
# returns de-packaging function w/ arguments to invoke with
return (unpackage_foo, (generated_module_name, time_exported,))
def unpackage_foo(
importer: PackageImporter, generated_module_name: str, time_exported: float
) -> Foo:
"""
Called by ``torch.package.PackageImporter``'s Pickler's ``persistent_load`` function
when depickling a Foo object.
Performs work of loading and returning a Foo instance from a ``torch.package`` archive.
"""
time_imported = time.clock_gettime(1)
foo = Foo(importer.load_text(generated_module_name, "foo.txt"))
foo.time_imported = time_imported
foo.time_exported = time_exported
return foo
# example of saving instances of class Foo
import torch
from torch.package import PackageImporter, PackageExporter
import foo
foo_1 = foo.Foo("foo_1 initial string")
foo_2 = foo.Foo("foo_2 initial string")
with PackageExporter('foo_package.pt') as pe:
# save as normal, no extra work necessary
pe.save_pickle('foo_collection', 'foo1.pkl', foo_1)
pe.save_pickle('foo_collection', 'foo2.pkl', foo_2)
pi = PackageImporter('foo_package.pt')
print(pi.file_structure())
imported_foo = pi.load_pickle('foo_collection', 'foo1.pkl')
print(f"foo_1 string: '{imported_foo.my_string}'")
print(f"foo_1 export time: {imported_foo.time_exported}")
print(f"foo_1 import time: {imported_foo.time_imported}")
# output of running above script
─── foo_package
├── foo-generated
│ ├── _0
│ │ └── foo.txt
│ └── _1
│ └── foo.txt
├── foo_collection
│ ├── foo1.pkl
│ └── foo2.pkl
└── foo.py
foo_1 string: 'foo_1 initial string, with reduction modification!'
foo_1 export time: 9857706.650140837
foo_1 import time: 9857706.652698385
在我的源代码中测试它是否在包内执行?¶
A 会将该属性添加到它初始化的每个模块中。您的代码可以检查
存在此属性来确定它是否在打包的上下文中执行。
__torch_package__
# In foo/bar.py:
if "__torch_package__" in dir(): # true if the code is being loaded from a package
def is_in_package():
return True
UserException = Exception
else:
def is_in_package():
return False
UserException = UnpackageableException
现在,代码的行为将有所不同,具体取决于它是通过 Python 环境正常导入还是从 .torch.package
from foo.bar import is_in_package
print(is_in_package()) # False
loaded_module = PackageImporter(my_package).import_module("foo.bar")
loaded_module.is_in_package() # True
警告: 一般来说,根据代码是否打包而具有不同的行为是不好的做法。这可能导致 难以调试的问题,这些问题对您导入代码的方式很敏感。如果您的软件包打算被大量使用,请考虑重组 您的代码,以便无论它如何加载,它的行为方式都相同。
将代码修补到包中?¶
提供了一种方法,允许将任意 Python 源代码保存到您选择的模块中。
save_source_string()
with PackageExporter(f) as exporter:
# Save the my_module.foo available in your current Python environment.
exporter.save_module("my_module.foo")
# This saves the provided string to my_module/foo.py in the package archive.
# It will override the my_module.foo that was previously saved.
exporter.save_source_string("my_module.foo", textwrap.dedent(
"""\
def my_function():
print('hello world')
"""
))
# If you want to treat my_module.bar as a package
# (e.g. save to `my_module/bar/__init__.py` instead of `my_module/bar.py)
# pass is_package=True,
exporter.save_source_string("my_module.bar",
"def foo(): print('hello')\n",
is_package=True)
importer = PackageImporter(f)
importer.import_module("my_module.foo").my_function() # prints 'hello world'
从打包的代码中访问包内容?¶
实现 importlib.resources API,以便从包内部访问资源。
with PackageExporter(f) as exporter:
# saves text to my_resource/a.txt in the archive
exporter.save_text("my_resource", "a.txt", "hello world!")
# saves the tensor to my_pickle/obj.pkl
exporter.save_pickle("my_pickle", "obj.pkl", torch.ones(2, 2))
# see below for module contents
exporter.save_module("foo")
exporter.save_module("bar")
API 允许从打包代码中访问资源。importlib.resources
# foo.py:
import importlib.resources
import my_resource
# returns "hello world!"
def get_my_resource():
return importlib.resources.read_text(my_resource, "a.txt")
使用是从打包代码中访问包内容的推荐方法,因为它符合
使用 Python 标准。但是,也可以从内部访问父实例本身
打包的代码。
importlib.resources
# bar.py:
import torch_package_importer # this is the PackageImporter that imported this module.
# Prints "hello world!", equivalent to importlib.resources.read_text
def get_my_resource():
return torch_package_importer.load_text("my_resource", "a.txt")
# You also do things that the importlib.resources API does not support, like loading
# a pickled object from the package.
def get_my_pickle():
return torch_package_importer.load_pickle("my_pickle", "obj.pkl")
区分打包代码和非打包代码?¶
要判断对象的代码是否来自 ,请使用该函数。
注意:如果对象来自包,但其定义来自标记为 或 from 的模块,
此检查将返回 。torch.package
torch.package.is_from_package()
extern
stdlib
False
importer = PackageImporter(f)
mod = importer.import_module('foo')
obj = importer.load_pickle('model', 'model.pkl')
txt = importer.load_text('text', 'my_test.txt')
assert is_from_package(mod)
assert is_from_package(obj)
assert not is_from_package(txt) # str is from stdlib, so this will return False
重新导出导入的对象?¶
要重新导出以前由 导入的对象,必须使 new
知道原始
对象,以便它可以找到对象的依赖项的源代码。
importer = PackageImporter(f)
obj = importer.load_pickle("model", "model.pkl")
# re-export obj in a new package
with PackageExporter(f2, importer=(importer, sys_importer)) as exporter:
exporter.save_pickle("model", "model.pkl", obj)
打包 TorchScript 模块?¶
要打包 TorchScript 模型,请使用与任何其他对象相同的 and API。
还支持保存作为属性或子模块的 TorchScript 对象,无需额外工作。save_pickle
load_pickle
# save TorchScript just like any other object
with PackageExporter(file_name) as e:
e.save_pickle("res", "script_model.pkl", scripted_model)
e.save_pickle("res", "mixed_model.pkl", python_model_with_scripted_submodule)
# load as normal
importer = PackageImporter(file_name)
loaded_script = importer.load_pickle("res", "script_model.pkl")
loaded_mixed = importer.load_pickle("res", "mixed_model.pkl"
解释¶
格式概述¶
文件是通常使用扩展名的 ZIP 存档。在 ZIP 存档中,有两种类型的文件:torch.package
.pt
框架文件,这些文件位于 .
.data/
User 文件,这是其他所有内容。
例如,这是完全打包的 ResNet 模型的样子:torchvision
resnet
├── .data # All framework-specific data is stored here.
│ │ # It's named to avoid conflicts with user-serialized code.
│ ├── 94286146172688.storage # tensor data
│ ├── 94286146172784.storage
│ ├── extern_modules # text file with names of extern modules (e.g. 'torch')
│ ├── version # version metadata
│ ├── ...
├── model # the pickled model
│ └── model.pkl
└── torchvision # all code dependencies are captured as source files
└── models
├── resnet.py
└── utils.py
框架文件¶
该目录由 torch.package 拥有,其内容被视为私有实现细节。
该格式不保证 的内容,但所做的任何更改都将向后兼容
(也就是说,较新版本的 PyTorch 将始终能够加载较旧版本的 )。.data/
torch.package
.data/
torch.packages
目前,该目录包含以下项:.data/
version
:序列化格式的版本号,以便导入基础设施知道如何加载此包。torch.package
extern_modules
:被视为 的模块列表。 模块将使用加载环境的 System Importer 导入。extern
extern
*.storage
:序列化的 Tensor 数据。
.data
├── 94286146172688.storage
├── 94286146172784.storage
├── extern_modules
├── version
├── ...
用户文件¶
存档中的所有其他文件都是由用户放在那里的。布局与 Python 常规包相同。要更深入地了解 Python 打包的工作原理, 请查阅这篇文章(它有点过时了,所以请仔细检查实现细节 替换为 Python 参考文档)。
<package root>
├── model # the pickled model
│ └── model.pkl
├── another_package
│ ├── __init__.py
│ ├── foo.txt # a resource file , see importlib.resources
│ └── ...
└── torchvision
└── models
├── resnet.py # torchvision.models.resnet
└── utils.py # torchvision.models.utils
如何
查找代码的依赖项¶
分析对象的依赖关系¶
当你发出 call 时,会正常 pickle 对象。然后,它使用 standard library 模块来解析 pickle 字节码。
save_pickle(obj, ...)
pickletools
在 pickle 中,一个对象与一个操作码一起保存,该操作码描述了在何处可以找到对象类型的实现,例如:GLOBAL
GLOBAL 'torchvision.models.resnet Resnet`
依赖项解析器将收集所有 op 并将它们标记为 pickled 对象的依赖项。
有关 pickling 和 pickle 格式的更多信息,请参阅 Python 文档。GLOBAL
分析模块的依赖项¶
当 Python 模块被标识为依赖项时,遍历模块的 python AST 表示形式,并使用
完全支持标准格式:、、 等。当这些 import 语句之一为
遇到,将导入的模块注册为依赖项,然后这些依赖项本身在相同的 AST walking way 中进行解析。torch.package
from x import y
import z
from w import v as u
torch.package
注意:AST 解析对语法的支持有限,并且不支持调用。一般来说,您应该
不希望 检测到动态导入。__import__(...)
importlib.import_module
torch.package
依赖关系管理¶
torch.package
自动查找您的代码和对象所依赖的 Python 模块。此过程称为依赖项解析。
对于依赖项解析程序找到的每个模块,您必须指定要执行的操作。
允许的操作包括:
intern
:将此模块放入包中。extern
:将此模块声明为软件包的外部依赖项。mock
:存根此模块。deny
:取决于此模块将在包导出期间引发错误。
最后,还有一个更重要的操作,从技术上讲不是 :torch.package
重构:删除或更改代码中的依赖项。
请注意,操作仅在整个 Python 模块上定义。没有办法从模块中“只”打包一个函数或类,而把其余的都省略掉。
这是设计使然。Python 不在模块中定义的对象之间提供清晰的边界。唯一定义的依赖关系组织单位是
模块,所以这就是 USE。torch.package
操作使用模式应用于模块。模式可以是模块名称 () 或 globs (如 )。您关联模式
使用 on 的方法执行操作,例如
"foo.bar"
"foo.**"
my_exporter.intern("torchvision.**")
my_exporter.extern("numpy")
如果模块与模式匹配,则会对其应用相应的操作。对于给定的模块,将按照定义模式的顺序检查模式。 ,将执行第一个操作。
intern
¶
如果一个模块是 -ed 的,它将被放入 package 中。intern
此操作是您的模型代码,或要打包的任何相关代码。例如,如果您尝试从 打包 ResNet,则
您将需要模块 torchvision.models.resnet。torchvision
intern
在包导入时,当你的打包代码尝试导入一个 -ed 模块时,PackageImporter 将在你的包中查找该模块。
如果找不到该模块,则会引发错误。这可确保每个 Slas 与 Load Environment 隔离 — 甚至
如果您在包和加载环境中都可用,
则只会使用
包。
intern
my_interned_module
注意:只有 Python 源模块可以被 -ed。其他类型的模块,如 C 扩展模块和字节码模块,如果
你试图去找他们。这些类型的模块需要 -ed 或 -ed。intern
intern
mock
extern
extern
¶
如果模块是 -ed 的,则不会打包。相反,它将被添加到此包的外部依赖项列表中。你可以找到这个
上的 列表。extern
package_exporter.extern_modules
在包导入时,当打包的代码尝试导入 -ed 模块时,将使用默认的 Python 导入器来查找
该模块,就像您执行了 .如果找不到该模块,则会引发错误。
extern
importlib.import_module("my_externed_module")
通过这种方式,您可以依赖第三方库,例如 和 从您的包中,而不必也打包它们。numpy
scipy
警告: 如果任何外部库以向后不兼容的方式更改,则您的包可能无法加载。如果您需要长期可重复性
对于您的包,请尝试限制您对 .extern
mock
¶
如果模块是 -ed 的,则不会打包。相反,一个 stub 模块将被打包在它的位置。stub 模块将允许您检索
对象(这样不会出错),但对该对象的任何使用都会引发 .mock
from my_mocked_module import foo
NotImplementedError
mock
应该用于您 “知道” 在加载的包中不需要的代码,但您仍然希望在未打包的内容中使用。
例如,初始化/配置代码,或仅用于调试/训练的代码。
警告: 一般来说,应该作为最后的手段使用。它引入了打包代码和非打包代码之间的行为差异。
这可能会导致以后的混淆。而是选择重构代码以删除不需要的依赖项。mock
重构¶
管理依赖项的最好方法是完全没有依赖项!通常,可以重构代码以删除不必要的依赖项。以下是一些 编写具有干净依赖项的代码的准则(这通常也是很好的做法!
仅包含您使用的内容。不要在代码中保留未使用的导入。依赖项解析器不够聪明,无法判断它们确实未使用, 并将尝试处理它们。
限定您的导入。例如,与其编写 import foo 然后使用 ,不如写 。这
精确地指定您的真实依赖关系 (),并让依赖关系解析程序知道您不需要所有 .foo.bar.baz
from foo.bar import baz
foo.bar
foo
将功能不相关的大文件拆分为较小的文件。如果您的模块包含大量不相关的功能,则任何模块
那依赖于 will 需要拉取许多不相关的依赖项,即使你只需要其中的一小部分。Prefer 改为定义
可以彼此独立打包的单一用途模块。utils
utils
模式¶
模式允许您使用方便的语法指定模块组。模式的语法和行为遵循 Bazel/Buck glob()。
我们尝试与模式匹配的模块称为 candidate。候选 Cookie 由一系列段组成,这些段由
分隔符字符串,例如 .foo.bar.baz
模式包含一个或多个段。细分可以是:
一个 Literals 字符串(例如 ),它完全匹配。
foo
包含通配符的字符串(例如 、 或 )。通配符匹配任何字符串,包括空字符串。
torch
foo*baz*
双通配符 ()。这将与零个或多个完整区段匹配。
**
例子:
torch.**
:匹配及其所有子模块,例如 和。torch
torch.nn
torch.nn.functional
torch.*
:匹配 或 ,但不匹配 或torch.nn
torch.functional
torch.nn.functional
torch
torch*.**
:匹配 、 和它们的所有子模块torch
torchvision
指定 action 时,您可以传递多个模式,例如
exporter.intern(["torchvision.models.**", "torchvision.utils.**"])
如果模块与任何模式匹配,则模块将与此操作匹配。
您还可以指定要排除的模式,例如
exporter.mock("**", exclude=["torchvision.**"])
如果模块与任何排除模式匹配,则模块将不会与此操作匹配。在这个例子中,我们模拟了除 及其子模块之外的所有模块。torchvision
当一个模块可能与多个操作匹配时,将执行定义的第一个操作。
锋利的边缘¶
避免在模块中使用全局状态¶
Python 使绑定对象和在模块级范围内运行代码变得非常容易。这通常很好,毕竟,函数和类都绑定到 以这种方式命名。然而,当你在模块范围内定义一个对象并打算改变它时,事情会变得更加复杂,引入 mutable 全局状态。
可变全局状态非常有用 — 它可以减少样板文件,允许打开注册到表中,等等。但是,除非非常小心地使用,否则它可以
与 一起使用时会导致并发症。torch.package
每个 Symbol 都会为其内容创建一个独立的环境。这很好,因为这意味着我们加载多个包并确保
它们彼此隔离,但是当以假定共享可变全局状态的方式编写模块时,此行为可能会产生难以调试的情况
错误。
如何
使包彼此隔离¶
每个实例都为其模块和对象创建一个独立的隔离环境。包中的模块只能导入
其他打包的模块或标记为 的模块 。如果您使用多个
实例加载单个包,您将获得
多个不交互的独立环境。
extern
这是通过使用自定义导入器扩展 Python 的导入基础设施来实现的。提供与 importer 相同的核心 API;即,它实现 AND 方法。
importlib
import_module
__import__
当你调用 时,
将构造并返回一个新模块,就像系统导入器所做的那样。
但是,
修补返回的模块以使用(即该
实例)以实现将来的导入
请求。
self
杂耍¶
为避免混淆(“此对象是我的包中的那个,还是我的 Python 环境中的对象?”),通过向所有导入的模块添加 mangle 前缀来破坏它们。
foo.bar
__name__
__file__
对于 ,名称(如 )变为 。__name__
torchvision.models.resnet18
<torch_package_0>.torchvision.models.resnet18
对于 ,名称(如 )变为 。__file__
torchvision/models/resnet18.py
<torch_package_0>.torchvision/modules/resnet18.py
名称重整有助于避免不同包之间无意中混淆模块名称,并通过制作堆栈跟踪和打印来帮助你进行调试
语句更清楚地表明它们是否引用打包代码。有关修饰的面向开发人员的详细信息,请参阅 。mangling.md
torch/package/
API 参考¶
- 类 torch.package 中。PackagingError(dependency_graph, debug=False)[来源]¶
当导出包时出现问题时,会引发此异常。 将尝试收集所有错误并呈现 他们立刻向你。
PackageExporter
- 类 torch.package 中。EmptyMatchError[来源]¶
当 mock 或 extern 被标记为 时,会引发一个异常,并且在打包过程中与任何模块都不匹配。
allow_empty=False
- 类 torch.package 中。PackageExporter(f, importer=<torch.package.importer._SysImporter object>, debug=False)[来源]¶
导出器允许您编写代码包、腌制的 Python 数据和 将任意二进制和文本资源合并到一个自包含的包中。
导入可以以封闭的方式加载此代码,以便加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。
包中包含的代码是从原始 source 时创建,并且文件格式是专门组织的 zip 文件。该包的未来用户可以解压缩该包,并编辑代码 以便对其执行自定义修改。
packages 的导入器确保模块中的代码只能从 在包中,但使用
. zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。
extern_modules
将源代码添加到包中时,导出器可以选择对其进行扫描 有关进一步的代码依赖项 ()。它查找 import 语句 解析对限定模块名称的相对引用,并执行用户指定的操作 (请参阅:
、 和
)。
dependencies=True
- all_paths(src, dst)[来源]¶
- 返回子图的点表示
,其中包含从 src 到 DST 的所有路径。
- 返回
包含从 src 到 dst 的所有路径的点表示形式。 (https://graphviz.org/doc/info/lang.html)
- 返回类型
- extern(include, *, exclude=(), allow_empty=True)[来源]¶
包含在包可以导入的外部模块列表中。 这将阻止依赖项发现保存 it 在包中。导入器将直接从标准导入系统加载外部模块。 extern 模块的代码也必须存在于加载包的进程中。
module
- 参数
include (Union[List[str], str]) – 字符串,例如 ,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如 中
描述。
"my_package.my_subpackage"
allow_empty (bool) – 一个可选标志,用于指定此调用指定的 extern 模块 到方法时必须与某个模块匹配。如果 extern 模块 glob pattern 使用 , 添加并在
任何模块匹配该模式之前调用(显式或通过),则会引发异常。如果 不会引发此类异常。
extern
allow_empty=False
__exit__
allow_empty=True
- intern(include, *, exclude=(), allow_empty=True)[来源]¶
指定应打包的模块。模块必须与某种模式匹配才能 包含在包中,并递归处理其依赖项。
intern
- 参数
include (Union[List[str], str]) – 字符串,例如 “my_package.my_subpackage”,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如 中所述
。
exclude (Union[List[str], str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。
allow_empty (bool) – 一个可选标志,用于指定此调用指定的实习生模块 到方法时必须与某个模块匹配。如果模块 glob pattern 与 一起添加,并被
调用(显式或通过) 在任何模块与该模式匹配之前,将引发异常。如果 ,则不会引发此类异常。
intern
intern
allow_empty=False
__exit__
allow_empty=True
- mock(include, *, exclude=(), allow_empty=True)[来源]¶
将一些必需的模块替换为 mock 实现。模拟模块将返回一个 fake object 来访问它的任何属性。因为我们逐个文件复制,所以依赖项解析有时会 查找由模型文件导入但其功能从未使用过的文件 (例如,自定义序列化代码或训练帮助程序)。 使用此函数可以模拟此功能,而无需修改原始代码。
- 参数
字符串(例如 )或字符串列表 以获取要模拟的模块的名称。字符串也可以是 glob 样式模式 字符串。与此模式匹配的任何必需依赖项 string 将自动模拟。
"my_package.my_subpackage"
- 例子:
'torch.**'
– 匹配和 torch 的所有子模块,例如 和torch
'torch.nn'
'torch.nn.functional'
'torch.*'
– 匹配 或 ,但不匹配'torch.nn'
'torch.functional'
'torch.nn.functional'
exclude (Union[List[str], str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。 例如 将模拟除 默认值:为 .
include='torch.**', exclude='torch.foo'
'torch.foo'
[]
allow_empty (bool) – 一个可选标志,用于指定此调用指定的模拟实现是否 到
方法时必须与某个模块匹配。如果 mock 是使用 , 添加的,并且
被调用(显式或通过),并且 mock 具有 未与正在导出的包使用的模块匹配,则会引发异常。 如果 ,则不会引发此类异常。
allow_empty=False
__exit__
allow_empty=True
- register_extern_hook(钩子)[来源]¶
在导出器上注册 extern 钩子。
每次模块与模式
匹配时,都会调用 hook。 它应具有以下签名:
hook(exporter: PackageExporter, module_name: str) -> None
Hook 将按照注册顺序被调用。
- 返回
一个句柄,可用于通过调用 来删除添加的钩子。
handle.remove()
- 返回类型
torch.utils.hooks.RemovableHandle
- register_intern_hook(钩子)[来源]¶
在导出器上注册 intern hook。
每次模块与模式
匹配时,都会调用 hook。 它应具有以下签名:
hook(exporter: PackageExporter, module_name: str) -> None
Hook 将按照注册顺序被调用。
- 返回
一个句柄,可用于通过调用 来删除添加的钩子。
handle.remove()
- 返回类型
torch.utils.hooks.RemovableHandle
- register_mock_hook(钩子)[来源]¶
在导出器上注册一个 mock hook。
每次模块与
模式匹配时,都会调用 hook。 它应具有以下签名:
hook(exporter: PackageExporter, module_name: str) -> None
Hook 将按照注册顺序被调用。
- 返回
一个句柄,可用于通过调用 来删除添加的钩子。
handle.remove()
- 返回类型
torch.utils.hooks.RemovableHandle
- save_module(module_name, dependencies=True)[来源]¶
将 的代码保存到包中。模块的代码使用路径进行解析,以查找 module 对象,然后使用其属性查找源代码。
module
importers
__file__
- save_pickle(package, resource, obj, dependencies=True, pickle_protocol=3)[来源]¶
使用 pickle 将 python 对象保存到存档中。等效于
但保存到 存档文件,而不是独立文件。标准 pickle 不保存代码,只保存对象。 如果为 true,则此方法还将扫描需要 modules 的腌制对象 以重新构造它们并保存相关代码。
dependencies
为了能够保存对象,其中 is ,必须根据顺序解析为对象的类。当保存 之前已经打包过,则导入器的方法需要出现在列表中 才能使它起作用。
type(obj).__name__
my_module.MyObject
my_module.MyObject
importer
import_module
importer
- save_source_file(module_name, file_or_directory, dependencies=True)[来源]¶
将本地文件系统添加到源码包中以提供代码 为。
file_or_directory
module_name
- 类 torch.package 中。PackageImporter(file_or_buffer, module_allowed=<function PackageImporter.<lambda>>)[来源]¶
导入器允许您加载通过
. 使用包中的文件以封闭方式加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。
packages 的导入器确保模块中的代码只能从 在包中,但在导出过程中明确列为 external 的模块除外。 zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。
extern_modules
- __init__(file_or_buffer, module_allowed=<function PackageImporter.<lambda>>)[来源]¶
打开以供导入。这将检查导入的包是否只需要模块 允许者
file_or_buffer
module_allowed
- import_module(name, package=None)[来源]¶
如果尚未加载 package,则从 package 中加载一个 module,然后返回 模块。模块在本地加载 添加到导入器中,并且将显示在 而不是 中。
self.modules
sys.modules