此页面由 Cloud Translation API 翻译。
Switch to English

Python互操作性

在TensorFlow.org上查看 在GitHub上查看源代码

Swift For TensorFlow支持Python互操作性。

您可以从Swift导入Python模块,调用Python函数,并在Swift和Python之间转换值。

 // comment so that Colab does not interpret `#if ...` as a comment
#if canImport(PythonKit)
    import PythonKit
#else
    import Python
#endif
print(Python.version)
 
3.6.9 (default, Apr 18 2020, 01:56:04) 
[GCC 8.4.0]

设置Python版本

默认情况下,当您import Python ,Swift会在系统库路径中搜索安装的最新版本的Python。要使用特定的Python安装,请将PYTHON_LIBRARY环境变量设置为安装提供的libpython共享库。例如:

export PYTHON_LIBRARY="~/anaconda3/lib/libpython3.7m.so"

在Python环境和平台之间,确切的文件名会有所不同。

另外,您可以设置PYTHON_VERSION环境变量,该变量指示Swift搜索系统库路径以找到匹配的Python版本。请注意, PYTHON_LIBRARY优先于PYTHON_VERSION

在代码中,您还可以调用PythonLibrary.useVersion函数,该函数等效于设置PYTHON_VERSION

 // PythonLibrary.useVersion(2)
// PythonLibrary.useVersion(3, 7)
 

注意:您应该在import Python之后立即运行PythonLibrary.useVersion ,然后再调用任何Python代码。它不能用于动态切换Python版本。

设置PYTHON_LOADER_LOGGING=1以查看Python库加载的调试输出

基本

在Swift中, PythonObject表示来自Python的对象。所有Python API都使用并返回PythonObject实例。

Swift中的基本类型(如数字和数组)可以转换为PythonObject 。在某些情况下(对于带PythonConvertible参数的文字和函数),转换是隐式进行的。要将Swift值显式转换为PythonObject ,请使用PythonObject初始化程序。

PythonObject定义了许多标准运算,包括数值运算,索引和迭代。

 // Convert standard Swift types to Python.
let pythonInt: PythonObject = 1
let pythonFloat: PythonObject = 3.0
let pythonString: PythonObject = "Hello Python!"
let pythonRange: PythonObject = PythonObject(5..<10)
let pythonArray: PythonObject = [1, 2, 3, 4]
let pythonDict: PythonObject = ["foo": [0], "bar": [1, 2, 3]]

// Perform standard operations on Python objects.
print(pythonInt + pythonFloat)
print(pythonString[0..<6])
print(pythonRange)
print(pythonArray[2])
print(pythonDict["bar"])
 
4.0
Hello 
slice(5, 10, None)
3
[1, 2, 3]

 // Convert Python objects back to Swift.
let int = Int(pythonInt)!
let float = Float(pythonFloat)!
let string = String(pythonString)!
let range = Range<Int>(pythonRange)!
let array: [Int] = Array(pythonArray)!
let dict: [String: [Int]] = Dictionary(pythonDict)!

// Perform standard operations.
// Outputs are the same as Python!
print(Float(int) + float)
print(string.prefix(6))
print(range)
print(array[2])
print(dict["bar"]!)
 
4.0
Hello 
5..<10
3
[1, 2, 3]

PythonObject定义了对许多标准Swift协议的一致性:

  • Equatable
  • Comparable
  • Hashable
  • SignedNumeric
  • Strideable
  • MutableCollection
  • 所有ExpressibleBy_Literal协议

请注意,这些一致性不是类型安全的:如果尝试从不兼容的PythonObject实例中使用协议功能,则会发生崩溃。

 let one: PythonObject = 1
print(one == one)
print(one < one)
print(one + one)

let array: PythonObject = [1, 2, 3]
for (i, x) in array.enumerated() {
  print(i, x)
}
 
true
false
2
0 1
1 2
2 3

要将元组从Python转换为Swift,您必须静态了解元组的重要性。

调用以下实例方法之一:

  • PythonObject.tuple2
  • PythonObject.tuple3
  • PythonObject.tuple4
 let pythonTuple = Python.tuple([1, 2, 3])
print(pythonTuple, Python.len(pythonTuple))

// Convert to Swift.
let tuple = pythonTuple.tuple3
print(tuple)
 
(1, 2, 3) 3
(1, 2, 3)

Python内置

通过全局Python接口访问Python内置函数。

 // `Python.builtins` is a dictionary of all Python builtins.
_ = Python.builtins

// Try some Python builtins.
print(Python.type(1))
print(Python.len([1, 2, 3]))
print(Python.sum([1, 2, 3]))
 
<class 'int'>
3
6

导入Python模块

使用Python.import导入Python模块。它的工作方式类似于Pythonimport关键字。

 let np = Python.import("numpy")
print(np)
let zeros = np.ones([2, 3])
print(zeros)
 
<module 'numpy' from '/usr/local/lib/python3.6/dist-packages/numpy/__init__.py'>
[[1. 1. 1.]
 [1. 1. 1.]]

使用抛出函数Python.attemptImport执行安全导入。

 let maybeModule = try? Python.attemptImport("nonexistent_module")
print(maybeModule)
 
nil

numpy.ndarray转换

以下Swift类型可以与numpy.ndarray相互转换:

  • Array<Element>
  • ShapedArray<Scalar>
  • Tensor<Scalar>

转换成功仅当dtype的的numpy.ndarray与兼容ElementScalar通用参数类型。

对于Array ,仅当numpy.ndarray为1-D时,才能从numpy转换。

 import TensorFlow

let numpyArray = np.ones([4], dtype: np.float32)
print("Swift type:", type(of: numpyArray))
print("Python type:", Python.type(numpyArray))
print(numpyArray.shape)
 
Swift type: PythonObject
Python type: <class 'numpy.ndarray'>
(4,)

 // Examples of converting `numpy.ndarray` to Swift types.
let array: [Float] = Array(numpy: numpyArray)!
let shapedArray = ShapedArray<Float>(numpy: numpyArray)!
let tensor = Tensor<Float>(numpy: numpyArray)!

// Examples of converting Swift types to `numpy.ndarray`.
print(array.makeNumpyArray())
print(shapedArray.makeNumpyArray())
print(tensor.makeNumpyArray())

// Examples with different dtypes.
let doubleArray: [Double] = Array(numpy: np.ones([3], dtype: np.float))!
let intTensor = Tensor<Int32>(numpy: np.ones([2, 3], dtype: np.int32))!
 
[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]

显示影像

您可以使用matplotlib在线显示图像,就像在Python笔记本中一样。

 // This cell is here to display plots inside a Jupyter Notebook.
// Do not copy it into another environment.
%include "EnableIPythonDisplay.swift"
IPythonDisplay.shell.enable_matplotlib("inline")
 
('inline', 'module://ipykernel.pylab.backend_inline')

 let np = Python.import("numpy")
let plt = Python.import("matplotlib.pyplot")

let time = np.arange(0, 10, 0.01)
let amplitude = np.exp(-0.1 * time)
let position = amplitude * np.sin(3 * time)

plt.figure(figsize: [15, 10])

plt.plot(time, position)
plt.plot(time, amplitude)
plt.plot(time, -amplitude)

plt.xlabel("Time (s)")
plt.ylabel("Position (m)")
plt.title("Oscillations")

plt.show()
 

png

None