iOS用Python開発環境Pythonista 3で外部ディスク上のファイルを扱う
価値ある情報をユーザー視点で発信するブログ

直射日光下でもよく見える珍しいメモリ液晶を搭載したSHARPの電子ノートがお気に入りです。

SHARPの電子ノートには感圧式のタッチパネルが付いていて、付属のペンなどで手書きで絵図を書き込むことができます。
最後にいつ充電したのか忘れてしまうぐらいバッテリーが長持ちし、今の時代に希少な、文房具のような使い勝手が気に入っています。
電子ノートは考えを整理するためのメモ書きや、3Dプリンタで作るもののスケッチを描くのに使っています。
電子ノートに書き留めたものを再利用することはほとんどないのですが、iPhoneとの連携を強化すると新たな使い道が見えてくるのかなと思い、環境改善を考えてみました。
もくじ
電子ノートはPCなどとの連携のために、USBマスストレージとして動作するUSB接続モードを備えます。

Apple Lightning – USBカメラアダプタなどを使ってiPhoneとUSBケーブルで接続。

電子ノートをUSB接続モードにすると、iPhoneのファイル.appでも電子ノートの中身を見ることができます。

電子ノートからPCなどへの画像の受け渡しは一つずつに限られいささか面倒なのですが、逆を言うとUSB接続モードで受け渡しする画像は自ずと一つに決定されます。
このことを利用し、セミオートでiPhoneに持っていく方法を考えてみました。
使った道具はPythonista 3というアプリです。
Pythonista 3はiOS上で使えるPythonで、自由度の高いセルフ開発環境です。
最近のアップデートでこのPythonista 3から念願の外部ファイルが参照可能になったのです。
このことに気付き、喜んでいるのは筆者ぐらいのものかと思いますが、個人的には大きな可能性を感じています。
Pythonista 3は1,200円の有料アプリなので、iOS標準搭載のショートカット.appを使えば済む場合はブログを書いて広く世に問う都合上、最近はできるだけ使わないようにしているのですが(※)、ショートカット.appの場合、外部ファイルを扱う場合は最初にファイル.app上で手動で選択せざるを得ず、便利感が薄いのでPythonista 3を使いました。

※導入の障壁が低いショートカットネタだと、記事の人気が高い傾向があるため
iPhoneにマウントした外部ディスク上のファイルをプログラマブルに扱う事例というのは希少かつ、こういうことができると分かれば応用可能なことが他にもたくさんあると思われるので紹介します。
外部のフォルダやファイルにアクセスできるPythonista 3ですが、最初に一度だけ手動で対象のフォルダ、ファイルに読み書きのアクセス権を付与する手順が必要です。
フォルダを指定した場合は、そのフォルダ以下のフォルダ、ファイルにもアクセス権が与えられます。
これはiPhoneにマウントした外部ディスクに限らず、iCloud Drive上のフォルダも同様です。
つまり、iCloud Driveに対応した他のアプリで保存したファイルにアクセスすることも可能ということです。
例えばiA Writerで作ったMarkdownにPythonista 3側からアクセスして、 何らかの処理を施すことも可能です。

前述の手順でアクセス権を与えましたが、そのフォルダにPythoninsta 3側からアクセスする場合はどうすればいいのでしょうか。
以下のような方法で当該フォルダ、ファイルのフルパスを調べることができます。



すると、選択したファイルまでのフルパスが得られます。
接続した電子ノート上の書き出し画像を選択した場合、恐らくは、以下のようなパスが表示されるかと思います。
"/private/var/mobile/Library/LiveFiles/com.apple.filesystems.userfsd/NO NAME/EXPORT/Page0001.jpg"
ここを対象にPythonista 3で処理を組めばよいというわけです。
ここまで説明したことを織り込んで作ったスクリプトが次に紹介するものです。
動作の概要は次のようなものです。
#!python3
import os, re, clipboard, console, time, shortcuts
from PIL import Image
# 電子ノートの書き出し画像を画像としてクリップボードにコピー
# moyashi ( @hitoriblog )
# 2020.07.10 Ver.0.0.1
# ----------設定-----------
# 電子ノートがマウントされる場所
mount_point = "/private/var/mobile/Library/LiveFiles/com.apple.filesystems.userfsd/"
# 電子ノートのボリューム名
volume_name = "NO NAME"
# 書き出し画像が保存されるフォルダ
export_dir = "EXPORT"
# 画像をコピーした後で起動するアプリのURL Scheme
app_to_launch = "mobilenotes://"
# ------------------------
# ボリュームのフルパス
target_volume = os.path.join(mount_point, volume_name)
# 書き出し画像が保存されるフォルダのフルパス
target_path = os.path.join(mount_point, volume_name, export_dir)
def copyImage():
# 電子ノートがマウントされている?
if os.path.exists(target_path):
# 書き出し画像のファイルを走査
files = os.scandir(target_path)
# 書き出し画像のファイル名の正規表現(Page0001.jpg等)
reobj = re.compile("Page\d{4}\.jpg")
# 書き出しフォルダの内容を一つずつ精査
for file in files:
# 書き出し画像のファイル名形式と一致したら
if (reobj.match(file.name)):
# 書き出し画像からPILのイメージを生成
im = Image.open(file.path)
# イメージが生成できたら
if (im):
# iOSのクリップボードにコピー
clipboard.set_image(im, format='png')
# コピー完了を表示
console.hud_alert(file.name + " をクリップボードにコピー")
return
# 主処理
def main():
# 10回ループ(インデックス付き)
for i, cnt in enumerate(range(10)):
# まだ電子ノートがマウントされていなかったら
if not os.path.exists(target_volume):
# 待機のアラートを表示
console.hud_alert("電子ノートの接続を待機... あと" + str(10 - i) + "秒")
# 1秒待つ
time.sleep(1)
else:
# 電子ノートがマウントされていたら
# 画像をクリップボードにコピー
copyImage()
# 画像をペーストするアプリを起動
# (クリップボードにコピーした画像をどう扱うするかは毎回違いそうなので以降は手動がよいと思いました)
shortcuts.open_url(app_to_launch)
break
main()
電子ノートをiPhoneに接続後、このスクリプトを起動すると電子ノート側で書き出した画像をクリップボードにコピーしてメモアプリを起動するので、あとは新規ページを作成してペーストするだけで電子ノートからの受け渡しが完了します。