ベスパリブ

プログラミングを主とした日記・備忘録です

gencache.EnsureModuleのメモ

gencache.EnsureModule()周りを色々調べたついでに備忘録を残します。

EnsureModule()を呼び出す理由

そもそもなんでgencache.EnsureModule()を呼び出さないといけないかというと、Dispatchする前にearly binding(事前バインディング)したいからなのです。

詳細は以下を参考にします。

Dispatch()でこれまで使用したことのないCOMオブジェクトを作成しようとすると、Pythonはオブジェクトが何を利用できるかわからないのでエラーが発生します。その場合、EnsureDispatch()を使うことで事前バインディングになるので、Pythonはオブジェクトが何を利用できるかわかるようになります。

win32.dynamic.Dispatch()というのもあり、こちらは常にlate binding(遅延バインディング)になるようです。

win32com.client.Dispatch()で動かない場合はgencache.EnsureModule()を使うことで、正しくキャッシュモジュールを生成することができます。

EnsureModule()の引数

上記の1個目のサイトを読むと、win32comの場所を調べると良さそうです。

>>> import win32com
>>> win32com.__file__ 
'C:\\Users\\XXXX\\AppData\\Local\\Continuum\\anaconda3\\envs\\projectX\\lib\\site-packages\\win32com\\__init__.py'
>>>

C:\Users\XXXX\AppData\Local\Continuum\anaconda3\envs\projectX\Lib\site-packages\win32com\client\gencache.pyがあったので、EnsureModule()の実装を見てみます。

def EnsureModule(typelibCLSID, lcid, major, minor, progressInstance = None, bValidateFile=not is_readonly, bForDemand = bForDemandDefault, bBuildHidden = 1):
    """Ensure Python support is loaded for a type library, generating if necessary.
  
  Given the IID, LCID and version information for a type library, check and if
  necessary (re)generate, then import the necessary support files. If we regenerate the file, there
  is no way to totally snuff out all instances of the old module in Python, and thus we will regenerate the file more than necessary,
  unless makepy/genpy is modified accordingly.
  
  
  Returns the Python module.  No exceptions are caught during the generate process.

  Params
  typelibCLSID -- IID of the type library.
  major -- Integer major version.
  minor -- Integer minor version
  lcid -- Integer LCID for the library.
  progressInstance -- Instance to use as progress indicator, or None to
                      use the GUI progress bar.
  bValidateFile -- Whether or not to perform cache validation or not
  bForDemand -- Should a complete generation happen now, or on demand?
  bBuildHidden -- Should hidden members/attributes etc be generated?
  """

lcidはロケールIDだとすると、gencache.EnsureModule('{D98A091D-3A0F-4C3E-B36E-61F62068D488}', 0, 1, 0)の引数は左から順に、

  • クラスID
  • ロケールID
  • メジャーバージョン番号
  • マイナーバージョン番号

ということだと思います。

また、適当にフォルダを適当に漁るとmakepy.pyを見つけることができます。

C:\Users\XXXX\AppData\Local\Continuum\anaconda3\envs\projectX\Lib\site-packages\win32com\client

のmakepy.pyの104-106行目になんか書いてあります。

       print(" >>> # Use these commands in Python code to auto generate .py support")
        print(" >>> from win32com.client import gencache")
        print(" >>> gencache.EnsureModule('%s', %s, %s, %s)" % (tlbSpec.clsid, tlbSpec.lcid, tlbSpec.major, tlbSpec.minor))

tlbSpecはおそらくキャッシュのTLB(Translation Lookaside Buffer)のことだと思います。なのでおそらく、クラスID等でアプリケーションを指定して、TLBでそのアプリケーションにメモリが割り当てられているといったことをしているのでしょう。