さり海馬

Thoughts walk away, blog stays.

管理ツールの「タスク」からpycronに移行しようとしてハマッたでござるの巻(追記あり)

表題の通り。スゲエ初歩的な部分でハマッたので、自戒の意味を込めて書いておきます。

会社のデータベースから毎晩深夜に必要なデータを引っ張り出して、それを加工・集計してレポートをメールで送る、というスクリプトを作って動かしてました。

Windows XP 上で動かしてるので、スクリプト自動起動には標準搭載されている管理ツールの「タスク」を使ってたんですが、これがまた使いにくい。やっぱ cron ライクなものの方が使いやすいということで、軽くググって見たらこういうのがありました。

pycron

Instructions
A good introductory article about pycron can be found at http://www.bigbluehost.com/article4.html
"This article will discuss using a Cron type system, as used on Unix and Linux systems, to bring the flexibility, scalability and a need for more out of a task automation tool, to the Win32 environment."

pycron is a cron service written in Python converted to an executable with py2exe. It's a successor to cron with a couple of changes and extensions:

インストールや設定とかは:

を参考にすると簡単に済みます。

ハマッたところ1: pycron のパラメータの指定

pycron には crontab.txt editor という便利なものが付いているのですが、こいつでタスクを設定するとき、実行するコマンドとそのコマンドのパラメータを与える部分があります。pythonスクリプトを実行しようとする場合、こういう風に設定しなければなりません(以下は俺の環境での設定なので、適宜変更して読んでください)。

  • command : C:\python26\python.exe
  • parameters: "C:\Documents and Settings\UserName-Ore\My Documents\python\report\reportGen.py"

注意すべきなのは、「パス内にスペースがあるときにはダブルクォートで囲まないといけません」ということです。すげえ初歩的でサーセン。管理ツールの「タスク」は囲まなくても大丈夫だったんで…。

ハマったところ2: スクリプト実行時の作業ディレクト

「タスク」では、実行時の作業ディレクトリはそのスクリプトのあるディレクトリになります。

一方、pycron で上記のように指定したとき、作業ディレクトリは pycron のインストールされているディレクトリになっているようです。

このため、スクリプト内部のパス指定を相対パスでやっていると、「タスク」では動いたものが pycron ではうまく動かない、なんてことになります(設定ファイルが見つからないとか、ファイルを書き出すディレクトリが違っているとか)。

対策として、スクリプトの最初のところで「このスクリプトがあるディレクトリに作業ディレクトリを変更する」という処理を追加しなければなりません。

あちこちググっていたら、こういう記事があって助かりました。そのままおいしくパクらせて頂きました。

os.chdir(os.path.dirname(sys.argv[0]) or '.')

これならpythonのor演算子の仕様に従って適切にos.chdir()が実行されるので万事OK。

ありがとうございましたm(__)m

さらにハマッたところ3: Excelの自動実行で「マクロが含まれています」が出てしまう

pycron の"Test Execution" でうまく行ったので安心していたら、本番の自動実行時にコケてました。問題は、Excel の自動実行。

  • command: C:\Program Files\Microsoft Office\Office\EXCEL.EXE
  • parameters: "C:\Documents and Settings\UserName-Ore\My Documents\python\report\reportgen.xls"

となっていて、このreportgen.xls(仮名)には、他のexcelファイルを読み込んでグラフを生成する処理をするVBAマクロが入っています。このマクロは"Sub Workbook_Open()"を利用して、ワークブックがオープンされると一連のマクロを実行するように仕組んでありました。

が、ここで問題が。"Test Execution"で実行すると問題ないのですが、自動実行に設定して時間が来たときに実行されると、この reportgen.xls を開くときに「マクロが含まれています」のダイアログが出て、ユーザー介入待ちになってしまいます。

どうしてこうなるのかは正直よく分からないのですが、たぶん、PyCronサービスから起動されることで何か違う権限になってしまっているのでしょう。

仕方がないので、苦肉の策としてVBScriptを使って、強制的にこのダイアログを迂回することにしました。

Option Explicit

Dim objExcel

' Excel Object を生成する
Set objExcel = CreateObject("Excel.Application")

' 画面表示をする
objExcel.visible = True

' 対象となるワークブックを開く
objExcel.Workbooks.Open "C:\Documents and Settings\UserName-Ore\My Documents\python\report\reportgen.xls"

' Excel Object を破棄する
Set objExcel = Nothing

そして pycron からはこのスクリプトを呼び出すことにしました。

…やっとうまく行きました。