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()
Folder
Folder
torch.package
对象本身是可直接打印的,并将打印出文件树表示形式。要过滤返回的内容,
使用 glob-style 和 filtering 参数。Folder
include
exclude
with PackageExporter('my_package.pt') as pe:
pe.save_pickle('models', 'model_1.pkl', mod)
# can limit printed items with include/exclude args
print(pe.file_structure(include=["**/utils.py", "**/*.pkl"], exclude="**/*.storages"))
importer = PackageImporter('my_package.pt')
print(importer.file_structure()) # will print out all files
输出:
# filtered with glob pattern:
# include=["**/utils.py", "**/*.pkl"], exclude="**/*.storages"
─── 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
您还可以使用该方法查询对象。Folder
has_file()
exporter_file_structure = exporter.file_structure()
found: bool = exporter_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/tens.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)
print(pe.file_structure())
pi = PackageImporter('foo_package.pt')
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_pacakge).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 one/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!", equivalient 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
:将被视为模块的模块列表将使用加载环境的系统导入器导入。extern:class:`PackageImporter`. ``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 模块上定义。没有办法从 module 中“只”打包一个函数或类,而把其余的都留下来。
这是设计使然。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
在包导入时,当 time 打包代码尝试导入 -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 参考¶
-
类 (dependency_graph)[来源]
torch.package.
PackagingError
¶ 当导出包时出现问题时,会引发此异常。 将尝试收集所有错误并呈现 他们立刻向你。
PackageExporter
-
类 [来源]
torch.package.
EmptyMatchError
¶ 当 mock 或 extern 被标记为 时,会引发一个异常,并且在打包过程中与任何模块都不匹配。
allow_empty=False
-
类 (f, importer=<torch.package.importer._SysImporter object>)[来源]
torch.package.
PackageExporter
¶ 导出器允许您编写代码包、腌制的 Python 数据和 将任意二进制和文本资源合并到一个自包含的包中。
导入可以以封闭的方式加载此代码,以便加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。
包中包含的代码是从原始 source 时创建,并且文件格式是专门组织的 zip 文件。该包的未来用户可以解压缩该包,并编辑代码 以便对其执行自定义修改。
packages 的导入器确保模块中的代码只能从 在包中,但使用
. zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。
extern_modules
将源代码添加到包中时,导出器可以选择对其进行扫描 有关进一步的代码依赖项 ()。它查找 import 语句 解析对限定模块名称的相对引用,并执行用户指定的操作 (请参阅:
、 和
)。
dependencies=True
-
__init__
(f, importer=<torch.package.importer._SysImporter object>)[来源]¶ 创建导出器。
- 参数
f – 要导出到的位置。可以是包含文件名的 / 对象 或二进制 I/O 对象。
string
Path
importer – 如果传递了单个 Importer,则使用它来搜索模块。 如果传递了一系列 importer,则将从它们中构造一个。
OrderedImporter
-
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 对象保存到存档中。等效于
但保存到 存档文件,而不是独立文件。Stanard 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
-
-
class (file_or_buffer, module_allowed=<function PackageImporter.<lambda>>)[来源]
torch.package.
PackageImporter
¶ 导入器允许您加载通过
. 使用包中的文件以封闭方式加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。
packages 的导入器确保模块中的代码只能从 在包中,但在导出过程中明确列为 external 的模块除外。 zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。
extern_modules
-
__init__
(file_or_buffer,module_allowed=<function PackageImporter.<lambda>>)[来源]¶ 打开以供导入。这将检查导入的包是否只需要模块 允许者
file_or_buffer
module_allowed
- 参数
- 提高
ImportError – 如果包将使用不允许的模块。
-
import_module
(name, package=None)[来源]¶ 如果尚未加载 package,则从 package 中加载一个 module,然后返回 模块。模块在本地加载 添加到导入器中,并且将显示在 而不是 中。
self.modules
sys.modules
-