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()¶
PackageImporter和PackageExporter提供一个方法,该方法将返回一个 Printable
和 queryable 对象。该对象是一个简单的目录结构,可用于浏览
的当前内容。file_structure()FolderFoldertorch.package
对象本身是可直接打印的,并将打印出文件树表示形式。要过滤返回的内容,
使用 glob-style 和 filtering 参数。Folderincludeexclude
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
您还可以使用该方法查询对象。Folderhas_file()
exporter_file_structure = exporter.file_structure()
found: bool = exporter_file_structure.has_file("package_a/subpackage.py")
了解为什么将给定模块作为依赖项包含在内?¶
假设有一个给定的模块 ,并且您想知道为什么您的fooPackageExporter作为依赖项拉入。foo
PackageExporter.get_rdeps()将返回所有直接依赖 的模块。foo
如果您想了解给定模块如何依赖于 ,srcfooPackageExporter.all_paths()方法将
返回一个 DOT 格式的图形,其中显示 和 之间的所有依赖关系路径。srcfoo
如果您只想查看PackageExporter,您可以使用PackageExporter.dependency_graph_string().
在我的包中包含任意资源并在以后访问它们?¶
PackageExporter公开了三种方法,这些方法允许您将
Python 对象、文本和二进制数据添加到包中。save_picklesave_textsave_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)
PackageImporter公开名为 的补充方法,并且允许您加载
来自包的 Python 对象、文本和二进制数据。load_pickleload_textload_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
在我的源代码中测试它是否在包内执行?¶
一个PackageImporter会将 attribute 添加到它初始化的每个模块中。您的代码可以检查
存在此属性来确定它是否在打包的上下文中执行。__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
警告: 一般来说,根据代码是否打包而具有不同的行为是不好的做法。这可能导致 难以调试的问题,这些问题对您导入代码的方式很敏感。如果您的软件包打算被大量使用,请考虑重组 您的代码,以便无论它如何加载,它的行为方式都相同。
将代码修补到包中?¶
PackageExporter提供了一种方法,允许将任意 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'
从打包的代码中访问包内容?¶
PackageImporter实现 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.resourcesPackageImporter实例本身
打包的代码。
# 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.packagetorch.package.is_from_package()externstdlibFalse
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
重新导出导入的对象?¶
要重新导出以前由PackageImporter,您必须将新的PackageExporter了解原始PackageImporter以便它可以找到对象依赖项的源代码。
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_pickleload_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"
解释¶
torch.package格式概述¶
文件是通常使用扩展名的 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
如何查找代码的依赖项torch.package¶
分析对象的依赖关系¶
当您发出呼叫时,save_pickle(obj, ...)PackageExporter将正常 pickle 对象。然后,它使用 standard library 模块来解析 pickle 字节码。pickletools
在 pickle 中,一个对象与一个作码一起保存,该作码描述了在何处可以找到对象类型的实现,例如:GLOBAL
GLOBAL 'torchvision.models.resnet Resnet`
依赖项解析器将收集所有 op 并将它们标记为 pickled 对象的依赖项。
有关 pickling 和 pickle 格式的更多信息,请参阅 Python 文档。GLOBAL
分析模块的依赖项¶
当 Python 模块被标识为依赖项时,遍历模块的 python AST 表示形式,并使用
完全支持标准格式:、、 等。当这些 import 语句之一为
遇到,将导入的模块注册为依赖项,然后这些依赖项本身在相同的 AST walking way 中进行解析。torch.packagefrom x import yimport zfrom w import v as utorch.package
注意:AST 解析对语法的支持有限,并且不支持调用。一般来说,您应该
不希望 检测到动态导入。__import__(...)importlib.import_moduletorch.package
依赖关系管理¶
torch.package自动查找您的代码和对象所依赖的 Python 模块。此过程称为依赖项解析。
对于依赖项解析程序找到的每个模块,您必须指定要执行的作。
允许的作包括:
- intern:将此模块放入包中。
- extern:将此模块声明为软件包的外部依赖项。
- mock:存根此模块。
- deny:取决于此模块将在包导出期间引发错误。
最后,还有一个更重要的作,从技术上讲不是 :torch.package
- 重构:删除或更改代码中的依赖项。 
请注意,作仅在整个 Python 模块上定义。没有办法从 module 中“只”打包一个函数或类,而把其余的都留下来。
这是设计使然。Python 不在模块中定义的对象之间提供清晰的边界。唯一定义的依赖关系组织单位是
模块,所以这就是 USE。torch.package
作使用模式应用于模块。模式可以是模块名称 () 或 globs (如 )。您关联模式
使用 methods on 的作"foo.bar""foo.**"PackageImporter,例如
my_exporter.intern("torchvision.**")
my_exporter.extern("numpy")
如果模块与模式匹配,则会对其应用相应的作。对于给定的模块,将按照定义模式的顺序检查模式。 ,将执行第一个作。
intern¶
如果一个模块是 -ed 的,它将被放入 package 中。intern
此作是您的模型代码,或要打包的任何相关代码。例如,如果您尝试从 打包 ResNet,则
您将需要模块 torchvision.models.resnet。torchvisionintern
在包导入时,当你的打包代码尝试导入一个 -ed 模块时,PackageImporter 将在你的包中查找该模块。
如果找不到该模块,则会引发错误。这确保了每个internPackageImporter与加载环境隔离 — 甚至
如果您的 package 和 loading environment 中都可用,则my_interned_modulePackageImporter将仅使用
包。
注意:只有 Python 源模块可以被 -ed。其他类型的模块,如 C 扩展模块和字节码模块,如果
你试图去找他们。这些类型的模块需要 -ed 或 -ed。interninternmockextern
extern¶
如果模块是 -ed 的,则不会打包。相反,它将被添加到此包的外部依赖项列表中。你可以找到这个
上的 列表。externpackage_exporter.extern_modules
在包导入时,当 time 打包代码尝试导入 -ed 模块时,externPackageImporter将使用默认的 Python 导入器来查找
该模块,就像您执行了 .如果找不到该模块,则会引发错误。importlib.import_module("my_externed_module")
通过这种方式,您可以依赖第三方库,例如 和 从您的包中,而不必也打包它们。numpyscipy
警告: 如果任何外部库以向后不兼容的方式更改,则您的包可能无法加载。如果您需要长期可重复性
对于您的包,请尝试限制您对 .extern
mock¶
如果模块是 -ed 的,则不会打包。相反,一个 stub 模块将被打包在它的位置。stub 模块将允许您检索
对象(这样不会出错),但对该对象的任何使用都会引发 .mockfrom my_mocked_module import fooNotImplementedError
mock应该用于您“知道”在加载的包中不需要的代码,但您仍然希望在未打包的内容中使用。
例如,初始化/配置代码,或仅用于调试/训练的代码。
警告: 一般来说,应该作为最后的手段使用。它引入了打包代码和非打包代码之间的行为差异。
这可能会导致以后的混淆。而是选择重构代码以删除不需要的依赖项。mock
重构¶
管理依赖项的最好方法是完全没有依赖项!通常,可以重构代码以删除不必要的依赖项。以下是一些 编写具有干净依赖项的代码的准则(这通常也是很好的做法!
仅包含您使用的内容。不要在我们的代码中留下未使用的导入。依赖项解析器不够聪明,无法判断它们确实未使用, 并将尝试处理它们。
限定您的导入。例如,与其编写 import foo 然后使用 ,不如写 。这
精确地指定您的真实依赖关系 (),并让依赖关系解析程序知道您不需要所有 .foo.bar.bazfrom foo.bar import bazfoo.barfoo
将功能不相关的大文件拆分为较小的文件。如果您的模块包含大量不相关的功能,则任何模块
那依赖于 will 需要拉取许多不相关的依赖项,即使你只需要其中的一小部分。Prefer 改为定义
可以彼此独立打包的单一用途模块。utilsutils
模式¶
模式允许您使用方便的语法指定模块组。模式的语法和行为遵循 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
当一个模块可能与多个作匹配时,将执行定义的第一个作。
torch.package锋利的边缘¶
避免在模块中使用全局状态¶
Python 使绑定对象和在模块级范围内运行代码变得非常容易。这通常很好,毕竟,函数和类都绑定到 以这种方式命名。然而,当你在模块范围内定义一个对象并打算改变它时,事情会变得更加复杂,引入 mutable 全局状态。
可变全局状态非常有用 — 它可以减少样板文件,允许打开注册到表中,等等。但是,除非非常小心地使用,否则它可以
与 一起使用时会导致并发症。torch.package
每PackageImporter为其内容创建独立的环境。这很好,因为这意味着我们加载多个包并确保
它们彼此隔离,但是当以假定共享可变全局状态的方式编写模块时,此行为可能会产生难以调试的情况
错误。
如何使包彼此隔离torch.package¶
每PackageImporter实例为其模块和对象创建一个独立的隔离环境。包中的模块只能导入
其他打包的模块或标记为 的模块 。如果您使用多个externPackageImporter实例来加载单个 package,您将获得
多个不交互的独立环境。
这是通过使用自定义导入器扩展 Python 的导入基础设施来实现的。PackageImporter提供与 importer 相同的核心 API;即,它实现 AND 方法。importlibimport_module__import__
调用PackageImporter.import_module(),PackageImporter将构造并返回一个新模块,就像系统导入器一样。
然而PackageImporter修补返回的模块以使用(即selfPackageImporterinstance) 来完成将来的导入
请求。
杂耍¶
为避免混淆(“此对象是我的包中的对象,还是我的 Python 环境中的对象?foo.barPackageImporter通过向所有导入的模块添加 mangle 前缀来破坏 and。__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.mdtorch/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 的导入器确保模块中的代码只能从 在包中,但显式列为 external using 的模块 - extern(). zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。- extern_modules- 将源代码添加到包中时,导出器可以选择对其进行扫描 有关进一步的代码依赖项 ()。它查找 import 语句 解析对限定模块名称的相对引用,并执行用户指定的作 (请参阅: - dependencies=True- extern(),- mock()和- intern()).- 
__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) 
 
 - 
deny(include, *, exclude=())[来源]¶
- 将名称与软件包可以导入的模块列表中的给定 glob 模式匹配的模块列入黑名单。 如果找到对任何匹配软件包的依赖项,则 - PackagingError被提升。
 - 
extern(include, *, exclude=(), allow_empty=True)[来源]¶
- 包含在包可以导入的外部模块列表中。 这将阻止依赖项发现保存 it 在包中。导入器将直接从标准导入系统加载外部模块。 extern 模块的代码也必须存在于加载包的进程中。 - module- 参数
- include (Union[List[str], str]) – 字符串,例如 ,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如 在 - "my_package.my_subpackage"- mock().
- allow_empty (bool) – 一个可选标志,用于指定此调用指定的 extern 模块 到方法时必须与某个模块匹配。如果 extern 模块 glob pattern 添加 ,并且 - extern- allow_empty=False- close()在任何模块匹配该模式之前被调用(显式或通过),则会引发异常。如果 不会引发此类异常。- __exit__- allow_empty=True
 
 
 - 
intern(include, *, exclude=(), allow_empty=True)[来源]¶
- 指定应打包的模块。模块必须与某种模式匹配才能 包含在包中,并递归处理其依赖项。 - intern- 参数
- include (Union[List[str], str]) – 字符串,例如 “my_package.my_subpackage”,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如 - mock().
- exclude (Union[List[str], str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。 
- allow_empty (bool) – 一个可选标志,用于指定此调用指定的实习生模块 到方法时必须与某个模块匹配。如果模块 glob pattern 添加 ,并且 - intern- intern- allow_empty=False- close()被调用(显式或通过) 在任何模块与该模式匹配之前,将引发异常。如果 ,则不会引发此类异常。- __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()method 必须与某个模块匹配。如果添加了 mock ,则使用 和- allow_empty=False- close()被调用(显式或通过),并且 mock 具有 未与正在导出的包使用的模块匹配,则会引发异常。 如果 ,则不会引发此类异常。- __exit__- allow_empty=True
 
 
 - 
register_extern_hook(钩子)[来源]¶
- 在导出器上注册 extern 钩子。 - 每次模块与 - extern()模式。 它应具有以下签名:- hook(exporter: PackageExporter, module_name: str) -> None - Hook 将按照注册顺序被调用。 - 返回
- 一个句柄,可用于通过调用 来删除添加的钩子。 - handle.remove()
- 返回类型
- torch.utils.hooks.RemovableHandle
 
 - 
register_intern_hook(钩子)[来源]¶
- 在导出器上注册 intern hook。 - 每次模块与 - intern()模式。 它应具有以下签名:- hook(exporter: PackageExporter, module_name: str) -> None - Hook 将按照注册顺序被调用。 - 返回
- 一个句柄,可用于通过调用 来删除添加的钩子。 - handle.remove()
- 返回类型
- torch.utils.hooks.RemovableHandle
 
 - 
register_mock_hook(钩子)[来源]¶
- 在导出器上注册一个 mock hook。 - 每次模块与 - mock()模式。 它应具有以下签名:- 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 对象保存到存档中。相当于 - torch.save()但存到 存档文件,而不是独立文件。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- 参数
- module_name (str) – 例如,将保存代码以为此包提供代码。 - "my_package.my_subpackage"
- file_or_directory (str) – 文件或代码目录的路径。当一个目录时,目录中的所有 python 文件 使用 - save_source_file().如果文件已命名,则处理代码 作为一个包。- "/__init__.py"
- dependencies (bool, optional) – 如果 ,我们将扫描源中的依赖项。 - True
 
 
 
- 
- 
class (file_or_buffer, module_allowed=<function PackageImporter.<lambda>>)[来源]torch.package.PackageImporter¶
- 导入器允许您加载写入包的代码 - PackageExporter. 使用包中的文件以封闭方式加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。- packages 的导入器确保模块中的代码只能从 在包中,但在导出过程中明确列为 external 的模块除外。 zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。 - extern_modules- 
__init__(file_or_buffer,module_allowed=<function PackageImporter.<lambda>>)[来源]¶
- 打开以供导入。这将检查导入的包是否只需要模块 允许者 - file_or_buffer- module_allowed- 参数
- 提高
- ImportError – 如果包将使用不允许的模块。 
 
 - 
id()[来源]¶
- 返回 torch.package 用于区分的内部标识符 - PackageImporter实例。 看来:- <torch_package_0> 
 - 
import_module(name, package=None)[来源]¶
- 如果尚未加载 package,则从 package 中加载一个 module,然后返回 模块。模块在本地加载 添加到导入器中,并且将显示在 而不是 中。 - self.modules- sys.modules
 - 
load_pickle(package, resource, map_location=None)[来源]¶
- 从包中解封资源,加载构造对象所需的任何模块 用 - import_module().
 
-