2012/01/29

os.walk()? os.path.walk()???

先日フォルダの中を再帰的に処理する必要があったときに、先輩にこんな愚痴をこぼしました。
Pythonのwalk()ってわかりにくいですよね。」
walk()というのはあるフォルダの中を再帰的に処理するためのメソッドです。
すると先輩は
「え?そう?わかりやすいと思うけど。」

まじですか。。。
俺がバカなだけですか???
と思っていたら、どうやらお互い違うもののことを言っていたらしいです。 

Pythonにはos.walk()とos.path.walk()があるって知ってました?
自分がわかりにくいと言ったのはos.path.walk()。
先輩がわかりやすいと言ったのはos.walk()

os.path.walk()はこんな感じ
C:\Python27\Lib\xmlの中のすべてのファイルを表示する
import os

## dirpathの中のパスをすべて表示する関数
#  os.path.walkの中で使うことで引数に以下の情報が入る
#
#  arg      = walk()の第3引数で指定できる自由になる引数(ここではNone)
#  dirpath  = 現在処理中のディレクトリパス
#  namelist = 現在処理中のディレクトリ内のすべてのアイテムの名前のリスト
#
def printall(arg, dirname, names):
    # 処理中のディレクトリパスとアイテム名を繋げたものがファイルだったら表示
    for name in names:
        fullpath = os.path.join(dirname, name)
        if os.path.isfile(fullpath):
            print fullpath


# ↑のprintall関数を指定してos.path.walk()を実行
os.path.walk(r'C:\Python27\Lib\xml', printall, None)
結果はこんな感じ(要素数:39)
# INFO : C:\Python27\Lib\xml\dom
# INFO : C:\Python27\Lib\xml\etree
# INFO : C:\Python27\Lib\xml\parsers
# INFO : C:\Python27\Lib\xml\sax
# INFO : C:\Python27\Lib\xml\__init__.py
# INFO : C:\Python27\Lib\xml\__init__.pyc
...
これってわかりにくいですよね。。。
walk()に自作の関数を食わせるって。
walk()に食わせた引数が自作関数の中でどう使われるのかも覚えにくいし。
os.walk()はどうかというとこんな感じ
import os

# os.walk()はディレクトリを受け取って中身を
# (処理中のディレクトリパス, その中のディレクトリリスト, ファイルリスト)というタプルを返す
# それをdirpath, dirnames, filenamesに割り振ってfilesの中身をまわしてdirpathと繋げて表示
#
for dirpath, dirnames, filenames in os.walk(r'C:\Python27\Lib\xml'):
    for f in filenames:
        print os.path.join(dirpath, f)
結果はこんな感じ(要素数:39) 順番は異なりますが要素数を見るとどちらもすべてのファイルを検出できてそう。
# INFO : C:\Python27\Lib\xml\__init__.py
# INFO : C:\Python27\Lib\xml\__init__.pyc
# INFO : C:\Python27\Lib\xml\dom\domreg.py
# INFO : C:\Python27\Lib\xml\dom\domreg.pyc
# INFO : C:\Python27\Lib\xml\dom\expatbuilder.py
# INFO : C:\Python27\Lib\xml\dom\minicompat.py
...
うーん、シンプル。。。 こりゃ確かにわかりやすいわ。 今後はこちら一択ですね。 ところでPython2.7のドキュメントを見るとos.path.walk()は廃止予定で3.0ではすでに削除されてるとか。。。 知らなかった。。。 Pythonクイックリファレンスはすごく詳しく書いてあって良いんですが2.3までのことしか書いてないので新しい情報は別から得ないとなぁ。

2011/12/26

シーン中のすべての~を取得

ずっと昔にどっかで見て使ったけどすっかり忘れちゃってた方法を、必要にかられて思い出しました。
次はもうちょっとすばやく思い出せるようにメモ。
シーン中のすべてのエクスプレッション、とかすべてのコンストレイン、とか探したくならないですか?
そんなときには「Application.FindObjects」らしいです。

シーン中のすべてのエクスプレッションを取得するには以下のようにするそうです。過去の自分によれば。
from siutils import *
oExps = si.FindObjects('', '{12723EB2-7DDB-11D0-A57F-00A0C91412DE}')
for i in oExps:
    print i.Definition.Value
すべてのPoseコンストレインはこう。
from siutils import *
oPoseCnss = si.FindObjects('', '{D42BBF71-3C47-11D2-8B42-00A024EE586F}')
for i in oPoseCnss:
    print i
この意味不明な文字はsiObjectCLSIDというものらしいです。
以下で選択オブジェクトのsiObjectCLSIDが取得できます。
from siutils import *
repo = siut.DataRepository
print repo.GetIdentifier(si.Selection(0), 3)

と、ここまで書いておそらくjunkiさんのページで見たのだと思い出しました。
ほんとにいつもお世話になりっぱなしです。

2011/09/28

SoftimageのオブジェクトをPythonクラスで拡張する

タイトルどおりSoftimageのオブジェクトをPythonクラスで拡張する方法。
これのミソは元々のSoftimageのオブジェクトの機能はちゃんと受け継いでるところです。
たとえばこんな感じ。
from win32com.client import *
si = Application

class MyObject(object):
    '''Softimageオブジェクトを拡張するクラス'''
    def __init__(self, input):
        '''初期化処理'''
        self.input = input  #元オブジェクトを格納


    def __getattr__(self, attr):
        '''このクラスにないアトリビュートが呼び出されたときに通る処理'''
        return getattr(self.input, attr)  #元オブジェクトのアトリビュートを取得して戻す


oNull = si.ActiveSceneRoot.AddNull() #ヌルを作成
MyNull= MyObject(oNull)                 #ヌルを引数に自前クラスのインスタンスを作成
LogMessage(MyNull.Name)
LogMessage(MyNull.posx.Value)
MyNull.AddNull('child')

これをSoftimageのスクリプトエディタに貼って実行するとどこにも定義してないけど.Nameも.posx.ValueもメソッドのAddNull()も使えます。

種は__getattr__とgetattrで、
__getattr__はクラスにないアトリビュートが呼ばれた時に実行されるメソッドで、呼び出そうとしたアトリビュートの代わりに戻り値を実行してくれるようです。
getattrは
getattr(オブジェクト, アトリビュート名)
でオブジェクトが持ってるアトリビュートを返してくれます。
なので
    def __getattr__(self, attr):
        return getattr(self.input, attr)
とすることで__getattr__を通る(存在しないアトリビュートが呼ばれた)時にインスタンスを作った時self.inputに格納しておいた元オブジェクトを使ってgetattr(self.input, attr)で元オブジェクトのアトリビュートを取得して実行するようになります。

これで好きな機能をバリバリ追加したカスタムオブジェクトが作れます。
たとえばこんな感じ。
アイコンを簡単に変更する機能をつけたヌルクラス

from win32com.client import *
si = Application

#ヌルアイコンの定数
NullIcon = {
   'None'       : 0,
   'Null'       : 1,
   'Rings'      : 2,
   'Arrow Rings': 4,
   'Box'        : 5,
   'Circle'     : 6,
   'Square'     : 7,
   'Diamond'    : 8,
   'Pyramid'    : 9,
   'Arrow'      : 10
   }


class MyNull(object):
 '''Nullを拡張するクラス'''
 def __init__(self, input):
  '''初期化処理'''
  self.input = input  #元オブジェクトを格納


 def __getattr__(self, attr):
  '''このクラスにないアトリビュートが呼び出されたときに通る処理'''
  return getattr(self.input, attr)  #元オブジェクトのアトリビュートを取得して戻す
  
  
 def SetIcon(self, sIconType='Null', nSize=1):
  '''アイコンを変更'''
  self.Parameters('primary_icon').Value = NullIcon[sIconType]
  self.Parameters('size').Value         = nSize
  
  
 def SetShadowIcon(self, sIconType='Null', nSize=1, lColor=[0,0,0]):
  '''
  シャドウアイコンを変更
  シャドウアイコンを変更するときはきっと通常のアイコンを使わないことが多いので非表示にする
  '''
  self.SetIcon('None', nSize) #通常のアイコンを非表示に
  self.Parameters('shadow_colour_custom').Value = True
  self.Parameters('shadow_icon').Value = NullIcon[sIconType]
  self.Parameters('R').Value = lColor[0]
  self.Parameters('G').Value = lColor[1]
  self.Parameters('B').Value = lColor[2]
  
  
oNull = si.ActiveSceneRoot.AddNull()     #ヌルを作成
Null = MyNull(oNull)                     #ヌルを引数に自前クラスのインスタンスを作成
Null.SetShadowIcon('Rings', 1, [1,1,0])  #シャドウアイコンを変更

2011/09/16

メソッドからクラス名を取得2

またまた自分用メモ。
こういうやり方もあるらしい。
これだとsys._getframe()の引数を変えることでクラスに限らずどんどんframeオブジェクトとやらを上がっていけるみたい。
import sys

def test():
	print sys._getframe(1).f_code.co_name

class TestClass:
    test()
 
T = TestClass()

2011/09/14

メソッドからクラス名を取得

自分メモ。
自分を呼び出したインスタンスのクラス名を表示。
class TestClass:
	def test(self):
		print locals()['self'].__class__.__name__

class TestClass2(TestClass):
	pass
		
T = TestClass()
T.test()

T = TestClass2()
T.test()

9/25 追記:
べつにこれでいいじゃん。。。
class TestClass:
	def test(self):
		print self.__class__.__name__

class TestClass2(TestClass):
	pass
		
T = TestClass()
T.test()

T = TestClass2()
T.test()
ま、なんかに使えるかな。きっと。

2011/06/30

Game Tools & Middleware Forum 2011

Game Tools & Middleware Forum 2011とその後の非公式飲みに行ってきました。
http://www.info-event.jp/gtmf2011/

フォーラム本編ではやはりUnityの存在感が強い印象を受けました。
今回もUnreal、国内エンジンOROCHIなどのゲームエンジンがセッションを持っていましたが、Unity含めゲームエンジン全般がどれも迅速なトライ&エラー、迅速なデバッグを追求していて、各機能の優劣はあれど基本的な考え方はほぼ同じように思えました。
Unreal、OROCHIが新たに組み込んだすばらしい機能のプレゼンをしていたのに対しUnityのほうは現在の日本のゲーム開発環境とゲームエンジンを使ったパイプラインの差をプレゼンしてくれていました。その上でUnityを使えばこんなにいいよ、と。
実際Unrealのほうがハイエンドで美しい絵が出せていますが、AssetStoreというアップルのAppStoreのようなものを開いて世界中の人が素材やカスタム環境をどんどん開発していけるコミュニティの力は大きいとです。

ということで自分もUnity使い始めてますがまだまだわからないことだらけ。
でもいろいろと参考になる動画やチュートリアルがあるみたいなんでコツコツやっていきます。

非公式飲みではいろんな人と話をすることができました。
こういう場には割と顔を出すほうなんですが今回は今まで知らなかった国内ゲーム開発のコミュニティや活動のことを知りました。
またこういう場に来ている人同士の人脈の広さや業界へのアンテナの張り方の広さを思い知りました。

うーん、みんなすごい!
来年もまた期待しちゃうなー