在 Swift 使用 Python 構建 App 克服 Python 的缺點!


本篇原文(標題:From Swift Import Python)刊登於作者 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

一直以來,Python 都在數據科學領域佔有領導地位,然而隨著要處理的數據量與日俱增,Python 的缺點就顯而易見了,就是處理速度慢、並行處理有所侷限、和缺乏型別安全性的問題,這些對大型 App 來說都是障礙。

很明顯地,Google 已經把 Swift 視為深度學習的未來,為 Tensorflow 在 Swift 上投資了重本。

不過,Python 擁有大量的資源庫,要逐漸擺脫它並不簡單,但是我們仍然可以利用它與 Swift 的互通性。

沒錯,你可以使用 PythonKit 框架從 Swift 運行 Python 程式碼,PythonKit 是 Swift for TensorFlow 項目中基於 Python 模塊的一個框架。

請注意,Python 在 iOS 上不可用,但你還是可以為 macOS 和 Linux 構建非常棒的工具 App。

PythonKit 的優點

  • 你的 Swift 程式碼可以直接存取豐富的 Python 模組和 Package。
  • Python 開發者可以輕鬆構建 macOS App,以運行自動化腳本 (script),並執行數值計算。
  • 你無需在 Swift 中加入巨大的 OpenCV 和 Tensorflow 框架,只要在系統上安裝 Python 副本 (counterparts),就可以在任何需要的 macOS App 中使用它。

在接下來的章節,我們會看看如何在一個 SwiftUI macOS App 中,設置 PythonKit 並執行一些有趣的任務。

在 macOS App 中加入 PythonKit

首先,讓我們建立一個新的 Xcode 專案,以 macOS 為目標,並使用 Swift Package Manager 加入以下的 Package dependancy:

.package(url: "https://github.com/pvieito/PythonKit.git", .branch("master")),
import pythonkit

操作步驟為:File -> Swift Packages -> Add Package Dependency -> 輸入這個 git 網址

現在,你可以在 Swift視圖中輸入 import PythonKit,接著要確認現在使用的 Python 版本,並如此更新版本:

print(Python.version)PythonLibrary.useVersion(2)
//or
PythonLibrary.useVersion(3, 8)

備註:PythonLibrary.useVersion 需要放於 import 的程式碼下面,因為你不可以在 Run-Time 時動態地修改 Python 版本。

接下來,請確保你已從 Signing and Capabilities section 移除了 App 沙盒,因為我們會在 mac 上直接使用 Python。

remove app sandbox

初次在 Swift 執行 Python 腳本

讓我們以 Python 函式在 .py 檔內寫 hello world。

def hello():
    return "Hello Swift, I'm Python"

然後存檔,並記住所存的路徑。

以下的 Swift 方法會呼叫上面的函式,並回傳結果:

func runPythonCode(){
  let sys = Python.import("sys")
  sys.path.append(dirPath)
  let example = Python.import("sample")
  let response = example.hello()
}

從以上的 Swift 程式碼中,我們注意到幾項事情:

  • dirPath 是檔案位置的路徑,我的檔案位置路徑是:/Users/anupamchugh/Desktop/workspace/
  • Python.import 是用來匯入 Python 模組的,以我們的範例來說,我們將匯入 sample.py 檔案,當中包含了我們的 hello world 程式碼。
  • example 是一個 PythonObject 型別的 Swift 實例,我們將在這裡呼叫 hello 函式。
  • 回應實例也是一個 PythonObject,能在範例中隱性地轉換成字串。

我們可以依下列做法,將 PythonObject 轉換成原生 Swift 的型別:

let str = String(pythonString)!
let arr = Array(pythonArray)!

轉換 Python 變數並回傳至 Swift

讓我們來看看一個典型範例,試著在 Swift 的 Python 函式中,轉換兩個變數的內容值:

def swap(a, b):
    a, b = b, a
    return a, b

現在,從 Swift 函式呼叫它,並取得結果:

func swapNumbersInPython(){
  let sys = Python.import("sys")
  sys.path.append(dirPath)
  let example = Python.import("sample")
  let response = example.swap(swapA, swapB)
  let arr : [Int] = Array(response)!
  swapA = arr[0]
  swapB = arr[1]
}

swapAswapB 都是 SwiftUI 的狀態變數,它們會在螢幕上被更新。

現在,讓我們利用以上的 Python 腳本執行 macOS SwiftUI App:

run python script

如此一來,我們就成功建置了第一個可以將 Swift 與 Python 互通的 macOS App。

但這樣還不夠。讓我們來撰寫一個更棒的 Python 腳本。

使用 Python 腳本下載影片 並顯示於 SwiftUI VideoPlayer

Python 有個非常受歡迎的 Package,叫做 youtube-dl,用來從 Youtube 或其他網站下載影片。

讓我們先將它下載到 mac,並以 Python3 執行下列的 pip 指令動作:

pip3 install youtube-dl

接著,在 Python 檔案內加入下列函式:

python-code

備註:你可以在Github 擷取程式碼。

linkpath 參數都是從 Swift 傳遞過來的,前者是影片連結,而後者是將影片保存的目錄路徑。

ydl.download() 會下載影片,然後我們會把 videoName 回傳到 Swift 程式碼:

func downloadVideo(link: String){
  let sys = Python.import("sys")
  sys.path.append(dirPath)
  let example = Python.import("sample")  let response = example.downloadVideo(link, dirPath)
  videoPath = String(response)
}

在 WWDC2020 中,SwiftUI 在 macOS 11.0 和 iOS 14 的裝置上,新增了 VideoPlayer 的內建支援。即使是 iOS 13 的裝置,你也可以利用 UIViewRepresentable 協定,來建立一個客製的影片視圖。

我們可以使用 videoPath,如此在 SwiftUI 顯示所下載的影片檔案:

let url = URL(fileURLWithPath:dirPath+videoPath)
VideoPlayer(player: AVPlayer(url: url))

讓我們運行以上的 mac App 來看看結果:

app-demo

影片是一段 Batman 的預告片

你可以在 GitHub 儲存庫 上找到 SwiftUI App 的完整程式碼與 Python 腳本。

總結

在本篇教學中,我們看到 Python、Swift 的互通性,並我們可以在 Swift 執行 Python 程式碼。除了影片下載器外,你還可以運行自動化任務,例如批次文件重新命名、硬碟空間分析功能等。

Python 和 Swift 是兩種語法簡潔的語言,儘管後者是深度學習的未來,但前者在未來幾年都會繼續扮演副手的重要角色。

本篇原文(標題:From Swift Import Python)刊登於作者 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

作者簡介:Anupam Chugh,深入探索 ML 及 AR 的 iOS Developer。喜愛撰寫關於想法、科技、與程式碼的文章。歡迎到我的 Blog 閱讀更多文章,或在 LinkedIn 上關注我。

譯者簡介:Oliver Chen-工程師,喜歡美麗的事物,所以也愛上 Apple,目前在 iOS 程式設計上仍是新手,正研讀 Swift 與 Sketch 中。生活另一個身份是兩個孩子的爸,喜歡和孩子一起玩樂高,幻想著某天自己開發的 App,可以讓孩子覺得老爸好棒!
聯絡方式:電郵 [email protected]


此文章為客座或轉載文章,由作者授權刊登,AppCoda編輯團隊編輯。有關文章詳情,請參考文首或文末的簡介。

blog comments powered by Disqus
Shares
Share This