本日は Blender2.8 の調査枠です。
Blender 2.8 の Python API ドキュメントを少しずつ読みつつ試していきます。
前回記事の続きです。
bluebirdofoz.hatenablog.com
Blender 2.8 Python API Documentation
以下のページを日本語訳しつつ実際に試して記事を進めていきます。
docs.blender.org
docs.blender.org
今日は「落とし穴」の「相対ファイルパス」と「Unicodeの問題」です。
相対ファイルパス
Blenderの相対ファイルパスは、sys や os などの標準Pythonモジュールと互換性がありません。
組み込みのPython関数は、blend ファイルのパスを示す "//" プレフィックスを認識しません。
この問題が発生する一般的なケースは、画像パスが関連付けられたマテリアルをエクスポートする場合です。
>>> bpy.path.abspath(image.filepath)
特にリンクされたライブラリからブレンダーデータを使用する場合、複雑です。
パスは開いている blend ファイルではなくライブラリを基準とするためです。
データブロックが外部 blend ファイルのものである場合は、bpy.types.ID からライブラリ引数を渡します。
>>> bpy.path.abspath(image.filepath, library=image.library)
Unicodeの問題
Pythonは多くの異なるエンコーディングをサポートしています。
latin1 または iso-8859-15 でスクリプトを記述出来ます。
PEP 263 を参照してください。
www.python.org
ただし、blend ファイルには明示的なエンコーディングがありません。
これは Blender の Python API の問題を複雑にします。
Python統合およびスクリプト作成者の問題を回避するために、blend ファイル内のすべての文字列に UTF-8, ASCII の互換性が必要と判断しました。
これは、例えば異なるエンコーディングの文字列をオブジェクト名に割り当てるとエラーが発生することを意味します。
ユーザーファイルシステム上の非 UTF-8 パスの存在を無視できないため、パスはこのルールの例外です。
これは、一見すると問題のないコードでもエラーが発生する可能性があることを意味します。
>>> print(bpy.data.filepath) UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-21: ordinal not in range(128)
>>> bpy.context.object.name = bpy.data.filepath Traceback (most recent call last): File "<blender_console>", line 1, in <module> TypeError: bpy_struct: item.attr= val: Object.name expected a string type, not str
ファイルシステムのエンコードの問題を回避する2つの記述方法を次に示します。
>>> print(repr(bpy.data.filepath))
>>> import os >>> filepath_bytes = os.fsencode(bpy.data.filepath) >>> filepath_utf8 = filepath_bytes.decode('utf-8', "replace") >>> bpy.context.object.name = filepath_utf8
Unicodeエンコーディング/デコーディングは包括的なPythonドキュメントで大きなトピックになっています。
・常にutf-8エンコードを使用するか、入力が不明な場合はutf-8に変換します。
・ファイルパスを文字列として直接操作することは避け、代わりに os.path 関数を使用してください。
・パスを操作するときは、組み込みの関数の代わりに os.fsencode() または os.fsdecode()を使用します。
・パスを表示するか、UI に含めるに 、repr(path を)最初に使用するか、"%r" % path フォーマットで使用します。