この記事は、Pythonista3 Advent Calendar 2022 の10日目の記事です。
一方的な偏った目線で、Pythonista3 を紹介していきます。
ほぼ毎日iPhone(Pythonista3)で、コーディングをしている者です。よろしくお願いします。
以下、私の2022年12月時点の環境です。
--- SYSTEM INFORMATION ---
* Pythonista 3.3 (330025), Default interpreter 3.6.1
* iOS 16.1.1, model iPhone12,1, resolution (portrait) 828.0 x 1792.0 @ 2.0) 828.0 x 1792.0 @ 2.0
他の環境(iPad や端末の種類、iOS のバージョン違い)では、意図としない挙動(エラーになる)なる場合もあります。ご了承ください。
ちなみに、model iPhone12,1
は、iPhone11 です。
グラフィクスプログラミングハラスメント
前回までは、絵を出すプログラミングでShader のGLSL や、path で線を引く方法を紹介しました。
しかも、かっこいい絵を出すテクニックではなく、グラフィクスプログラミングをするための環境作りのみで、残りはみなさんにぶん投げる着地でございました。。。
path を引く際の数式をゴリゴリ紹介し、「こんないい感じになるんやで!」と、したかったのですが、センス・知識・紹介技量全てが足りず、いつかは紹介したいと思っております。
今回は、前回のpath とは違うpath を使って、絵を出すとは違うプログラミングをやっていこうと思います。
Pythonista3 から、Pythonista3 を覗き見る
Pythonista3 では「ScriptLibrary」内に自分のコードを置いたり、「ExternalFiles」で外部のフォルダやファイルにアクセスできたり、モジュール関係のファイルが入っているディレクトリがあったり、名称によりさまざまな意味でディレクトリが多数存在します。
- ScriptLibrary
- 主に自分の作成したコードを格納する場所
- ExternalFiles
- 外部(ファイルApp や他のアプリ)のファイルやフォルダを参照する
- Python Modules
- 標準モジュール、Pythonista3 で用意されているモジュールの格納場所
- 自作モジュールも格納できるよう準備されれいる
それらは、Pythonista3 のGUI でタップすることで、行ったり来たり選んだりが、気軽にできます。
またGUI 操作以外でも、Python は、標準でファイル・ディレクトリ操作ができるモジュールがあるので、コードから該当のファイルへアクセスしたり、新規作成等が可能です。
これまででも、特にEditor Action を使ったコードでファイルの新規作成などで使ってきました。
プログラミングをするにあたり、フォルダ構成の理解は必要な部分かと思われます。
まずは、簡単なコードで状況を確認してみましょう。
注意事項
免責事項として書いています。
アプリやOS 内部構造を操作することになります。
変更や削除で、アプリやOS が起動不可になることもありえます。
不具合に関しては自己責任でお願い致します。
pathlib
モジュール
11.1. pathlib --- オブジェクト指向のファイルシステムパス — Python 3.6.15 ドキュメント
Pythonista3 が、3.6
なので一応3.6.15
のバージョンで見ています。
os
モジュール等でも可能ですが、私的にpathlib
が使いやすいので、pathlib
で確認していきます。os
、sys
等が使いやすい方は、脳内読み替えでお願いいたします🙇
公式ドキュメントで迷子になった時は、こちらにお世話になってるます。
Python, pathlibの使い方(パスをオブジェクトとして操作・処理) | note.nkmk.me
現在位置確認
適当な位置でファイルを作成し、現在地を見てみます:
from pathlib import Path
path = Path()
abs_path = path.resolve()
print(abs_path)
pathlib.Path.resolve | pathlib --- オブジェクト指向のファイルシステムパス — Python 3.11.0b5 ドキュメント
ScriptLibrary 直下に作成したファイルから呼び出した場合は以下の結果が出力されます。
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/Documents
それぞれ-違う-英数字
には、個別端末(?)ごとに違う表記となります。
ExternalFiles からファイルApp のダウンロード
直下にあるコードを実行すると以下の結果で出力されるのが確認できます。
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/File Provider Storage/Downloads
注意点としては、ExternalFiles へ取り込む際にPython/Text File...
ではなくFolder...
から、適用したいフォルダを選択することです。単品ファイルを選択すると取得できません。
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/File Provider Storage/Downloads/pathtest.py", line 4, in <module>
abs_path = path.resolve()
File "/var/containers/Bundle/Application/それぞれ-違う-英数字/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/pathlib.py", line 1123, in resolve
s = self._flavour.resolve(self, strict=strict)
File "/var/containers/Bundle/Application/それぞれ-違う-英数字/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/pathlib.py", line 349, in resolve
base = '' if path.is_absolute() else os.getcwd()
PermissionError: [Errno 1] Operation not permitted
うーん、面白いですね☺️
ScriptLibrary 直下のフォルダやファイル
ScriptLibrary 直下に(わかりやすく)ファイル名をrootThisFile.py
として作成して、同階層に何があるか見てみましょう。
from pathlib import Path
path = Path()
abs_path = path.resolve()
print(abs_path)
for f in abs_path.glob('*'):
print(f'\t- {f.name}')
.glob('*')
として、ゴリっと取得したものを出力しています。
Python, pathlibでファイル一覧を取得(glob, iterdir) | note.nkmk.me
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/Documents
- site-packages-3
- Welcome.md
- rootThisFile.py
- _objc_exception.txt
- site-packages-2
- Templates
- site-packages
- myScripts
- .style.yapf
- Examples
- .Trash
- ws
脚注を加えます
ScriptLibrary で、確認できるものや自分で作成したもの以外に意外なフォルダやファイルが出てきました。
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/Documents
- site-packages-3 ← (*1)
- Welcome.md
- rootThisFile.py ← 今回実行したスクリプト
- _objc_exception.txt ← objc_util 系のエラーログ
- site-packages-2 ← (*1)
- Templates ← (*2)
- site-packages ← (*1)
- myScripts ← 私のEditor Action 用スクリプトが格納されているやつ
- .style.yapf ← (*3)
- Examples
- .Trash ← (*3)
- ws ← 私がコードを作成して編集する作業用フォルダ
GUI 上で見えている部分が、実は同じ階層で管理されているのですね。
(*1)
のsite-packages
たちは、自分で入れたモジュールが格納されているディレクトリです。
また(*3)
ドットファイル(先頭に.
があるファイルやフォルダ)は、GUI では非表示設定になっています。
Pythonista3 (GUI)上で見えている情報と、出力した階層の情報が違うことがわかりますね。
一つ上の階層は?
もっと、探訪したくなりますね!
pathlib
の.parent
で上の階層から呼び出してみましょう。
from pathlib import Path
path = Path()
abs_path = path.resolve()
parent_path = abs_path.parent
print(parent_path)
for f in parent_path.glob('*'):
print(f'\t- {f.name}')
なんということでしょう。見たことがないファイルたちが出てきました。
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3
- ExtensionShortcuts.json
- Documents
- Bookmarks.plist
- .matplotlib
- Library
- Favorites.plist
- Tabs.plist
- KeyboardShortcutDefinitions.json
- Recents.plist
Documents
が、我々が普段何かしらしているディレクトリです。
.parent
を追加して、更なる上の階層を見てみましょうか:
from pathlib import Path
path = Path()
abs_path = path.resolve()
parent_path = abs_path.parent.parent
print(parent_path)
for f in parent_path.glob('*'):
print(f'\t- {f.name}')
Pythonista3 アプリ自体のディレクトリになるのでしょうか?
だんだんと表示される情報が減ってきました。
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字
- .com.apple.mobile_container_manager.metadata.plist
- Library
- Pythonista3
ファイルに何が書かれているか気になる
階層の探訪をしてきました。フォルダ以外にファイルも表示されているので、見たことある拡張子(.json
など)の中を読んでみたくなりますよね?私はなります☺️
pathlib
モジュールは、open
を使ったwith
を使わずとも、1行でテキスト情報を取得できるます。
.read_text
を使って、中身を見てみましょう。
Python, pathlibでファイルの作成・open・読み書き・削除 | note.nkmk.me
読み取るコード
少々手間ですが、一度ファイル情報を取得してから、取得したいファイルを確認後、指定ファイルを見ていくことにします。
.json
ファイルを探す
from pathlib import Path
root_path = Path().home()
print('検索するディレクトリ:')
print(root_path)
for f in root_path.glob('*.json'):
print('\n.json ファイル ---')
print(f)
print('--- /')
.home
で、Pythonista3
ディレクトリ内から探します。
ScriptLibrary 直下の場合、.parent
一回呼び出しの階層です。
検索するディレクトリ:
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3
.json ファイル ---
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/ExtensionShortcuts.json
--- /
.json ファイル ---
/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/KeyboardShortcutDefinitions.json
--- /
2つの.json
ファイルが見つかりました。
.json
ファイルを見る
ExtensionShortcuts.json
を見てみることにしましょう。
console より出力された、ファイルパスを何かしらでコピーし:
from pathlib import Path
json_file = Path(
'/private/var/mobile/Containers/Shared/AppGroup/それぞれ-違う-英数字/Pythonista3/ExtensionShortcuts.json'
)
txt = json_file.read_text()
print(txt)
[{"scriptName":"Examples\/Extension\/Copy Photo Location.py","iconName":"ios7-world","iconColor":"6CB8FF"},{"scriptName":"Examples\/Extension\/Image Histogram.py","iconName":"stats-bars","iconColor":"6CFF7F"},{"scriptName":"Examples\/Extension\/Text Statistics.py","iconName":"document-text","iconColor":"FFBD62"},{"scriptName":"Examples\/Extension\/URL to QR Code.py","iconName":"grid","iconColor":"62F0FF"},{"scriptName":"Examples\/Extension\/Preview Markdown.py","iconName":"ios7-eye","iconColor":"4A525A"}]
無事に取得できました。
整形すると:
[
{
"scriptName": "Examples/Extension/Copy Photo Location.py",
"iconName": "ios7-world",
"iconColor": "6CB8FF"
},
{
"scriptName": "Examples/Extension/Image Histogram.py",
"iconName": "stats-bars",
"iconColor": "6CFF7F"
},
{
"scriptName": "Examples/Extension/Text Statistics.py",
"iconName": "document-text",
"iconColor": "FFBD62"
},
{
"scriptName": "Examples/Extension/URL to QR Code.py",
"iconName": "grid",
"iconColor": "62F0FF"
},
{
"scriptName": "Examples/Extension/Preview Markdown.py",
"iconName": "ios7-eye",
"iconColor": "4A525A"
}
]
Share Sheet Extension | App Extensions and Shortcuts — Python 3.6.1 documentation
Share Sheet Extension の情報が入っている.json
ファイルのようですね。
こんな所に格納され設定されていたのですね😎
次回は
pathlib
で、ディレクトリを移動しながらprint
で情報を出力しました。
GUI のフォルダ構成とは裏腹に、内部の構成がされてましたね。
気になるフォルダ名、ファイル名を探して中身を確認してみてください☺️
とはいえ、毎回print
確認をするのは面倒で骨が折れます。。。
そこで、次回はwebbrowser
モジュール等を使ってディレクトリ探訪をもっと楽にしましょう。
標準モジュールである、webbrowser
ですがPythonista3 用に一部カスタマイズされているのです☺️
ここまで、読んでいただきありがとうございました。
せんでん
Discord
Pythonista3 の日本語コミュニティーがあります。みなさん優しくて、わからないところも親身に教えてくれるのでこの機会に覗いてみてください。
書籍
iPhone/iPad でプログラミングする最強の本。
その他
- サンプルコード
Pythonista3 Advent Calendar 2022 でのコードをまとめているリポジトリがあります。
コードのエラーや変なところや改善点など。ご指摘やPR お待ちしておりますー
なんしかガチャガチャしていますが、お気兼ねなくお声がけくださいませー
やれるか、やれないか。ではなく、やるんだけども、紹介説明することは尽きないと思うけど、締め切り守れるか?って話よ!(クズ)
— pome-ta (@pome_ta93) November 4, 2022
Pythonista3 Advent Calendar 2022 https://t.co/JKUxA525Pt #Qiita
- GitHub
基本的にGitHub にコードをあげているので、何にハマって何を実装しているのか観測できると思います。