قابلیت همکاری پایتون

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub

Swift For TensorFlow از قابلیت همکاری پایتون پشتیبانی می کند.

می توانید ماژول های پایتون را از سویفت وارد کنید، توابع پایتون را فراخوانی کنید و مقادیر را بین سویفت و پایتون تبدیل کنید.

import PythonKit
print(Python.version)
3.6.9 (default, Oct  8 2020, 12:12:24) 
[GCC 8.4.0]

تنظیم نسخه پایتون

به‌طور پیش‌فرض، وقتی import Python ، سوئیفت مسیرهای کتابخانه سیستم را برای جدیدترین نسخه نصب‌شده پایتون جستجو می‌کند. برای استفاده از یک نصب خاص پایتون، متغیر محیطی PYTHON_LIBRARY را روی کتابخانه اشتراکی libpython که توسط نصب ارائه شده است، تنظیم کنید. مثلا:

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

نام دقیق فایل در محیط‌ها و پلتفرم‌های پایتون متفاوت خواهد بود.

همچنین، می‌توانید متغیر محیطی PYTHON_VERSION را تنظیم کنید، که به Swift دستور می‌دهد مسیرهای کتابخانه سیستم را برای نسخه پایتون منطبق جستجو کند. توجه داشته باشید که PYTHON_LIBRARY بر PYTHON_VERSION ارجحیت دارد.

در کد، می‌توانید تابع PythonLibrary.useVersion را نیز فراخوانی کنید، که معادل تنظیم PYTHON_VERSION است.

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

توجه: باید PythonLibrary.useVersion درست پس از import Python ، قبل از فراخوانی هر کد پایتون اجرا کنید. نمی توان از آن برای تعویض پویا نسخه های پایتون استفاده کرد.

PYTHON_LOADER_LOGGING=1 برای مشاهده خروجی اشکال زدایی برای بارگیری کتابخانه پایتون تنظیم کنید.

مبانی

در سوئیفت، PythonObject یک شی از پایتون را نشان می دهد. همه APIهای پایتون از نمونه‌های PythonObject استفاده می‌کنند و برمی‌گردانند.

انواع پایه در سوئیفت (مانند اعداد و آرایه ها) به PythonObject قابل تبدیل هستند. در برخی موارد (برای کلمات و توابعی که از آرگومان‌های PythonConvertible استفاده می‌کنند)، تبدیل به طور ضمنی اتفاق می‌افتد. برای ارسال صریح مقدار سوئیفت به 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 انطباق ها را با بسیاری از پروتکل های استاندارد سوئیفت تعریف می کند:

  • 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

برای تبدیل تاپل ها از پایتون به سوئیفت، باید به صورت ایستا آریتی تاپل را بدانید.

یکی از روش های نمونه زیر را فراخوانی کنید:

  • 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.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.import استفاده کنید. مانند کلمه کلیدی 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

انواع سوئیفت زیر را می توان به 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 نمایش دهید، درست مانند نوت بوک های پایتون.

// 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.