Совместимость Python

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть исходный код на GitHub

Swift For TensorFlow поддерживает совместимость Python.

Вы можете импортировать модули Python из Swift, вызывать функции Python и преобразовывать значения между Swift и Python.

import PythonKit
print(Python.version)
3.6.9 (default, Oct  8 2020, 12:12:24) 
[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)

Примечание. Вам следует запустить PythonLibrary.useVersion сразу после import Python , прежде чем вызывать какой-либо код Python. Его нельзя использовать для динамического переключения версий Python.

Установите PYTHON_LOADER_LOGGING=1 , чтобы увидеть выходные данные отладки для загрузки библиотеки Python .

Основы

В Swift PythonObject представляет объект Python. Все API Python используют и возвращают экземпляры 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. Оно работает как ключевое слово import в Python .

let np = Python.import("numpy")
print(np)
let zeros = np.ones([2, 3])
print(zeros)
<module 'numpy' from '/tmpfs/src/tf_docs_env/lib/python3.6/site-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 совместим с типом универсального параметра Element или Scalar .

Для Array преобразование из numpy завершается успешно, только если numpy.ndarray имеет значение 1-D.

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"
print(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

Use `print()` to show values.

,

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть исходный код на GitHub

Swift For TensorFlow поддерживает совместимость Python.

Вы можете импортировать модули Python из Swift, вызывать функции Python и преобразовывать значения между Swift и Python.

import PythonKit
print(Python.version)
3.6.9 (default, Oct  8 2020, 12:12:24) 
[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)

Примечание. Вам следует запустить PythonLibrary.useVersion сразу после import Python , прежде чем вызывать какой-либо код Python. Его нельзя использовать для динамического переключения версий Python.

Установите PYTHON_LOADER_LOGGING=1 , чтобы увидеть выходные данные отладки для загрузки библиотеки Python .

Основы

В Swift PythonObject представляет объект Python. Все API Python используют и возвращают экземпляры 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. Оно работает как ключевое слово import в Python .

let np = Python.import("numpy")
print(np)
let zeros = np.ones([2, 3])
print(zeros)
<module 'numpy' from '/tmpfs/src/tf_docs_env/lib/python3.6/site-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 совместим с типом универсального параметра Element или Scalar .

Для Array преобразование из numpy завершается успешно, только если numpy.ndarray имеет значение 1-D.

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"
print(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

Use `print()` to show values.