目录

torch.package

torch.package添加了对创建包含任意 PyTorch 代码。这些包可以保存、共享、用于加载和执行模型 在以后或在其他计算机上部署,甚至可以使用 .torch::deploy

本文档包含教程、作指南、说明和 API 参考,其中 将帮助您了解有关和如何使用它的更多信息。torch.package

警告

此模块依赖于不安全的模块。仅解包您信任的数据。pickle

可以构造恶意的 pickle 数据,这些数据将在解封期间执行任意代码。 切勿解压缩可能来自不受信任的来源或可能已被篡改的数据。

有关更多信息,请查看该模块的文档pickle

教程

打包您的第一个模型

Colab 上提供了指导您打包和解包简单模型的教程。 完成本练习后,您将熟悉用于创建和使用 API 的基本 API Torch 软件包。

我该如何...

查看包内有什么?

将包视为 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()

PackageImporterPackageExporter提供一个方法,该方法将返回一个 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__

步骤:

  1. 在 target 类上定义方法。此方法应将类实例保存在包内,并应返回相应解包函数的元组,其中包含调用解包函数所需的参数。当遇到目标类的实例时,将调用此方法。__reduce_package__(self, exporter: PackageExporter)PackageExporter

  2. 为类定义一个解包函数。此解包函数应执行重新构造和返回类实例的工作。函数签名的第一个参数应为实例,其余参数为用户定义。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 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.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

  • 包含通配符的字符串(例如 、 或 )。通配符匹配任何字符串,包括空字符串。torchfoo*baz*

  • 双通配符 ()。这将与零个或多个完整区段匹配。**

例子:

  • torch.**:匹配及其所有子模块,例如 和。torchtorch.nntorch.nn.functional

  • torch.*:匹配 或 ,但不匹配 或torch.nntorch.functionaltorch.nn.functionaltorch

  • torch*.**:匹配 、 和它们的所有子模块torchtorchvision

指定 action 时,您可以传递多个模式,例如

exporter.intern(["torchvision.models.**", "torchvision.utils.**"])

如果模块与任何模式匹配,则模块将与此作匹配。

您还可以指定要排除的模式,例如

exporter.mock("**", exclude=["torchvision.**"])

如果模块与任何排除模式匹配,则模块将不会与此作匹配。在这个例子中,我们模拟了除 及其子模块之外的所有模块。torchvision

当一个模块可能与多个作匹配时,将执行定义的第一个作。

torch.package锋利的边缘

避免在模块中使用全局状态

Python 使绑定对象和在模块级范围内运行代码变得非常容易。这通常很好,毕竟,函数和类都绑定到 以这种方式命名。然而,当你在模块范围内定义一个对象并打算改变它时,事情会变得更加复杂,引入 mutable 全局状态。

可变全局状态非常有用 — 它可以减少样板文件,允许打开注册到表中,等等。但是,除非非常小心地使用,否则它可以 与 一起使用时会导致并发症。torch.package

PackageImporter为其内容创建独立的环境。这很好,因为这意味着我们加载多个包并确保 它们彼此隔离,但是当以假定共享可变全局状态的方式编写模块时,此行为可能会产生难以调试的情况 错误。

类型不在包和加载环境之间共享

您从PackageImporter将是特定于该导入器的类的版本。例如:

from foo import MyClass

my_class_instance = MyClass()

with PackageExporter(f) as exporter:
    exporter.save_module("foo")

importer = PackageImporter(f)
imported_MyClass = importer.import_module("foo").MyClass

assert isinstance(my_class_instance, MyClass)  # works
assert isinstance(my_class_instance, imported_MyClass)  # ERROR!

在此示例中,它们不是同一类型。在这个特定示例中,并且恰好具有 相同的实现,所以你可能会觉得把它们看作是同一个类是可以的。但是考虑一下来自 older 包具有完全不同的实现 — 在这种情况下,将它们视为同一个类是不安全的。MyClassimport_MyClassMyClassimport_MyClassimport_MyClassMyClass

在后台,每个导入器都有一个前缀,允许它唯一标识类:

print(MyClass.__name__)  # prints "foo.MyClass"
print(imported_MyClass.__name__)  # prints <torch_package_0>.foo.MyClass

这意味着当其中一个参数来自包而另一个参数不是时,你不应该期望检查有效。如果您需要这个 功能,请考虑以下选项:isinstance

  • 进行鸭子类型化(仅使用类,而不是显式检查它是否属于给定类型)。

  • 使类型关系成为类协定的显式部分。例如,您可以添加属性标记并让客户端代码检查 of 的值,而不是直接检查类型。self.handler = "handle_me_this_way"handler

如何使包彼此隔离torch.package

PackageImporterinstance 为其模块和对象创建一个独立的隔离环境。包中的模块只能导入 其他打包的模块或标记为 的模块 。如果您使用多个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

fimporter=<torch.package.importer._SysImporter object>[来源]torch.package.PackageExporter

导出器允许您编写代码包、腌制的 Python 数据和 将任意二进制和文本资源合并到一个自包含的包中。

导入可以以封闭的方式加载此代码,以便加载代码 而不是普通的 Python 导入系统。这允许 用于打包 PyTorch 模型代码和数据,以便可以运行 在服务器上或将来用于迁移学习。

包中包含的代码是从原始 source 时创建,并且文件格式是专门组织的 zip 文件。该包的未来用户可以解压缩该包,并编辑代码 以便对其执行自定义修改。

packages 的导入器确保模块中的代码只能从 在包中,但显式列为 external using 的模块extern(). zip 存档中的文件列出了软件包外部依赖的所有模块。 这可以防止包在本地运行的 “隐式” 依赖项,因为它正在导入 本地安装的软件包,但在将软件包复制到另一台计算机时失败。extern_modules

将源代码添加到包中时,导出器可以选择对其进行扫描 有关进一步的代码依赖项 ()。它查找 import 语句 解析对限定模块名称的相对引用,并执行用户指定的作 (请参阅:dependencies=Trueextern(),mock()intern()).

__init__(fimporter=<torch.package.importer._SysImporter object>[来源]

创建导出器。

参数
  • f – 要导出到的位置。可以是包含文件名的 / 对象 或二进制 I/O 对象。stringPath

  • importer – 如果传递了单个 Importer,则使用它来搜索模块。 如果传递了一系列 importer,则将从它们中构造一个。OrderedImporter

add_dependency(module_name,dependencies=True[来源]

给定一个模块,根据模式将其添加到依赖项图 由用户指定。

all_paths(srcdst[来源]
返回子图的点表示

,其中包含从 src 到 DST 的所有路径。

返回

包含从 src 到 dst 的所有路径的点表示形式。 (https://graphviz.org/doc/info/lang.html)

close()[来源]

将软件包写入文件系统。之后的任何调用close()现在无效。 最好改用资源防护语法:

with PackageExporter("file.zip") as e:
    ...
denied_modules()[来源]

返回当前被拒绝的所有模块。

返回

一个包含模块名称的列表,这些模块将是 在此包中被拒绝。

deny(include*exclude=()[来源]

将名称与软件包可以导入的模块列表中的给定 glob 模式匹配的模块列入黑名单。 如果找到对任何匹配软件包的依赖项,则PackagingError被提升。

参数
  • includeUnion[List[str]str]) – 字符串,例如 ,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如"my_package.my_subpackage"mock().

  • excludeUnion[List[str]str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。

dependency_graph_string()[来源]

返回包中依赖项的二合图字符串表示形式。

返回

package 中依赖项的字符串表示形式。

extern(include*exclude=()allow_empty=True[来源]

包含在包可以导入的外部模块列表中。 这将阻止依赖项发现保存 it 在包中。导入器将直接从标准导入系统加载外部模块。 extern 模块的代码也必须存在于加载包的进程中。module

参数
  • includeUnion[List[str]str]) – 字符串,例如 ,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如 在"my_package.my_subpackage"mock().

  • excludeUnion[List[str]str]) – 一个可选模式,用于排除与 include 字符串。

  • allow_emptybool) – 一个可选标志,用于指定此调用指定的 extern 模块 到方法时必须与某个模块匹配。如果 extern 模块 glob pattern 添加 ,并且externallow_empty=Falseclose()在任何模块匹配该模式之前被调用(显式或通过),则会引发异常。如果 不会引发此类异常。__exit__allow_empty=True

externed_modules()[来源]

返回当前 externed 的所有模块。

返回

一个包含模块名称的列表,这些模块将是 externed 在此包中。

get_rdeps(module_name[来源]

返回依赖于 module 的所有模块的列表。module_name

返回

包含依赖于 的模块名称的列表。module_name

get_unique_id()[来源]

获取 ID。此 ID 保证此包仅分发一次。

intern(include*exclude=()allow_empty=True[来源]

指定应打包的模块。模块必须与某种模式匹配才能 包含在包中,并递归处理其依赖项。intern

参数
  • includeUnion[List[str]str]) – 字符串,例如 “my_package.my_subpackage”,或字符串列表 以获取要 externed 的模块的名称。这也可以是 glob 样式模式,如mock().

  • excludeUnion[List[str]str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。

  • allow_emptybool) – 一个可选标志,用于指定此调用指定的实习生模块 到方法时必须与某个模块匹配。如果模块 glob pattern 添加 ,并且interninternallow_empty=Falseclose()被调用(显式或通过) 在任何模块与该模式匹配之前,将引发异常。如果 ,则不会引发此类异常。__exit__allow_empty=True

interned_modules()[来源]

返回当前实习的所有模块。

返回

一个包含模块名称的列表,这些模块将是 在这个包中实习。

mock(include*exclude=()allow_empty=True[来源]

将一些必需的模块替换为 mock 实现。模拟模块将返回一个 fake object 来访问它的任何属性。因为我们逐个文件复制,所以依赖项解析有时会 查找由模型文件导入但其功能从未使用过的文件 (例如,自定义序列化代码或训练帮助程序)。 使用此函数可以模拟此功能,而无需修改原始代码。

参数
  • 包括Union[List[str]str]) –

    字符串(例如 )或字符串列表 以获取要模拟的模块的名称。字符串也可以是 glob 样式模式 字符串。与此模式匹配的任何必需依赖项 string 将自动模拟。"my_package.my_subpackage"

    例子:

    'torch.**'– 匹配和 torch 的所有子模块,例如 和torch'torch.nn''torch.nn.functional'

    'torch.*'– 匹配 或 ,但不匹配'torch.nn''torch.functional''torch.nn.functional'

  • excludeUnion[List[str]str]) – 一种可选模式,用于排除与 include 字符串匹配的某些模式。 例如 将模拟除 默认值:为 .include='torch.**', exclude='torch.foo''torch.foo'[]

  • allow_emptybool) – 一个可选标志,用于指定此调用指定的模拟实现是否 到mock()method 必须与某个模块匹配。如果添加了 mock ,则使用 和allow_empty=Falseclose()被调用(显式或通过),并且 mock 具有 未与正在导出的包使用的模块匹配,则会引发异常。 如果 ,则不会引发此类异常。__exit__allow_empty=True

mocked_modules()[来源]

返回当前被模拟的所有模块。

返回

一个包含模块名称的列表,这些模块将是 在这个包中被模拟。

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_binary(packageresourcebinary[来源]

将原始字节保存到包中。

参数
  • packagestr) – 此资源应包含的模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称,用于标识要加载的资源。

  • binarystr) – 要保存的数据。

save_module(module_name,dependencies=True[来源]

将 的代码保存到包中。模块的代码使用路径进行解析,以查找 module 对象,然后使用其属性查找源代码。moduleimporters__file__

参数
  • module_namestr) – 例如,将保存代码以提供代码 对于此软件包。my_package.my_subpackage

  • dependenciesbooloptional) – 如果 ,我们将扫描源中的依赖项。True

save_pickle(packageresourceobjdependencies=Truepickle_protocol=3[来源]

使用 pickle 将 python 对象保存到存档中。相当于torch.save()但存到 存档文件,而不是独立文件。Stanard pickle 不保存代码,只保存对象。 如果为 true,则此方法还将扫描需要 modules 的腌制对象 以重新构造它们并保存相关代码。dependencies

为了能够保存对象,其中 is ,必须根据顺序解析为对象的类。当保存 之前已经打包过,则导入器的方法需要出现在列表中 才能使它起作用。type(obj).__name__my_module.MyObjectmy_module.MyObjectimporterimport_moduleimporter

参数
  • packagestr) – 此资源应放入的模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称,用于标识要加载的资源。

  • objAny) – 要保存的对象必须是 picklable 的。

  • dependenciesbooloptional) – 如果 ,我们将扫描源中的依赖项。True

save_source_file(module_namefile_or_directorydependencies=True[来源]

将本地文件系统添加到源码包中以提供代码 为。file_or_directorymodule_name

参数
  • module_namestr) – 例如,将保存代码以为此包提供代码。"my_package.my_subpackage"

  • file_or_directorystr) – 文件或代码目录的路径。当一个目录时,目录中的所有 python 文件 使用save_source_file().如果文件已命名,则处理代码 作为一个包。"/__init__.py"

  • dependenciesbooloptional) – 如果 ,我们将扫描源中的依赖项。True

save_source_string(module_namesrcis_package=Falsedependencies=True[来源]

在导出的包中添加为 的源代码。srcmodule_name

参数
  • module_namestr) – 例如,将保存代码以为此包提供代码。my_package.my_subpackage

  • srcstr) – 要为此软件包保存的 Python 源代码。

  • is_packagebooloptional) – 如果 ,则此模块被视为一个包。包可以有子模块 (例如 ),并且可以在其中保存资源。默认为 。Truemy_package.my_subpackage.my_subsubpackageFalse

  • dependenciesbooloptional) – 如果 ,我们将扫描源中的依赖项。True

save_text(资源文本[来源]

将文本数据保存到包中。

参数
  • packagestr) – 此资源应包含的模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称,用于标识要加载的资源。

  • textstr) – 要保存的内容。

class file_or_buffermodule_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_buffermodule_allowed

参数
  • file_or_buffer – 一个类似文件的对象(必须实现 、 、 和 )、 字符串或包含文件名的对象。read()readline()tell()seek()os.PathLike

  • module_allowedCallable[[str]bool]optional) – 一种确定是否为外部提供的模块的方法 应该允许。可用于确保加载的软件包不依赖于服务器 不支持。默认允许任何内容。

提高

ImportError – 如果包将使用不允许的模块。

file_structure(*include='**'exclude=())[来源]

返回包的 zipfile 的文件结构表示形式。

参数
  • includeUnion[List[str]str]) – 可选字符串,例如 ,或可选的字符串列表 以获取 zipfile 表示中要包含的文件的名称。这也可以是 glob 样式模式,如"my_package.my_subpackage"PackageExporter.mock()

  • excludeUnion[List[str]str]) – 一种可选模式,用于排除名称与模式匹配的文件。

返回

Directory

id()[来源]

返回 torch.package 用于区分的内部标识符PackageImporter实例。 看来:

<torch_package_0>
import_module(namepackage=None[来源]

如果尚未加载 package,则从 package 中加载一个 module,然后返回 模块。模块在本地加载 添加到导入器中,并且将显示在 而不是 中。self.modulessys.modules

参数
  • namestr) – 要加载的模块的完全限定名称。

  • package[type]optional) – 未使用,但存在以匹配 importlib.import_module 的签名。默认为 。None

返回

(可能已经)加载的模块。

返回类型

类型。模块类型

load_binary(资源[来源]

加载原始字节。

参数
  • packagestr) – 模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称。

返回

加载的数据。

返回类型

字节

load_pickle(packageresourcemap_location=None[来源]

从包中解封资源,加载构造对象所需的任何模块 用import_module().

参数
  • packagestr) – 模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称。

  • map_location – 传递给 torch.load 以确定如何将张量映射到设备。默认为 。None

返回

解封的对象。

返回类型

任何

load_text(资源encoding='utf-8'errors='strict'[来源]

加载字符串。

参数
  • packagestr) – 模块 package 的名称(例如 )。"my_package.my_subpackage"

  • resourcestr) – 资源的唯一名称。

  • encodingstroptional) – 传递给 .默认为 。decode'utf-8'

  • errorsstroptional) – 传递给 .默认为 。decode'strict'

返回

加载的文本。

返回类型

str

class nameis_dir[来源]torch.package.Directory

文件结构表示形式。组织为具有 他们的目录子项。软件包的目录是通过调用PackageImporter.file_structure().

has_file(文件名[来源]

检查文件是否存在于Directory.

参数

filenamestr) – 要搜索的文件的路径。

返回

如果Directory包含指定的文件。

返回类型

布尔

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源