Macのモジュールを使う


Mac Pythonについてのページ(よ)>


ここには、PythonのMac独自のモジュールを使った例をいくつか書いておきます。
そのうち少しづつ増やしていこうと思います。

しかしながら、わたしが知っている程度の簡単なものしか書けません。ごめんなさい。

未整理のものは、わたしのPythonTipsのページにあります。

誤っているところや、おかしいところがあるかもしれません。お気づきの点がございましたら、わたしまでご連絡いただければ幸いです。


このページの目次


ファイルダイアログで開く(macfsモジュール)

Pythonのファイルの命令(open)だけだと、パスを書かなければなりませんし、白紙アイコンのファイルしかできません。Macでお馴染みのファイルダイアログを使いたいものです。それには、macfsモジュールのStandardGetFile、StandardPutFileを使います。

MacPython2.3ではmacfs.StandardGetFileではなくEasyDialogs.AskFileForOpen、macfs.StandardGetFileではなくEasyDialogs.AskFileForSaveを使うそうです。

(1)既存のファイルを開く場合

import macfs
#ファイルを選択
fss, ok = macfs.PromptGetFile('ファイルを選んで!', 'TEXT')
#PromptGetFileの初めの引数はプロンプト文、第2引数以降はオプション(なくてもよい)で
#加えることのできるファイルタイプで、このタイプのファイルのみ表示します。
#macfs.PromptGetFile('ファイルを選んで!', 'TEXT', 'GIFf')のようにタイプを複数指定できます。
#第2引数を指定しなかった場合には全ファイルが表示されます。
#プロンプト文を使わない場合はStandardGetFileを使って、StandardGetFile('TEXT')とします。
#fssにはFsspecオブジェクトと呼ばれるものが代入されます。
#okには、ダイアログでCancelが押されずにファイルが選択されると1が代入されます。
if ok:
	#もし、Cancelボタンが押されずファイルが選ばれていたら
	path = fss.as_pathname()
	#Fsspecオブジェクトであるfssに対してas_pathnameメソッドを呼び出すと、
	#fssのパスが返されます。それをpathに代入します。
	#ここで通常通り(?)ファイルを開きます。
	fp = open(path,'r')
	strings = fp.read()
	fp.close()
	print strings

蛇足:『PromptGetFileは2つの要素をもつタプルを返す』と考えて、以下のようにしてもいいのですが、Mac:Demoの例をみると、上のようにしていますね。

import macfs
fss = macfs.PromptGetFile('ファイルを選んで!', 'TEXT', 'GIFf')
if fss[1]:
	path = fss[0].as_pathname()
	fp = open(path,'r')
	strings = fp.read()
	fp.close()
	print strings

(2)新規にファイル作成する場合

import macfs
#ファイルのディレクトリと名前を選択
fss, ok = macfs.StandardPutFile('ディレクトリとファイル名を選んで!', '名称未設定')
#StandardPutFileの初めの引数はプロンプト文、第2引数は保存するファイル名として
#表示されます。
#okには、ダイアログでCancelが押されなかった場合に1が代入されます。
#fssにはFsspecオブジェクトが代入されます。
if ok:
	#もし、Cancelボタンが押されずファイルが指定されたら
	path = fss.as_pathname()
	#Fsspecオブジェクトであるfssに対してas_pathnameメソッドを呼び出すと、
	#fssのパスが返されます。それをpathに代入します。
	#ここで通常通り(?)ファイルを開きます。
	fp = open(path,'w')
	fp.write('あいうえお')
	fp.close()
	#これで'名称未設定'ファイルに書き込めましたが、白紙のアイコンにしちゃうのは
	#Macユーザとして不満なので、ファイルのクリエータとタイプを設定しましょう。
	fss.SetCreatorType('Pyth', 'TEXT')
	#これで'名称未設定'ファイルがPythonのテキストファイルのアイコンで表示されます。

初期設定フォルダ/ゴミ箱のパスを得る(macfs、MACFS)

MACFSモジュールにはmacfsで使う定数がおさめられています。
以下は、起動ディスクのデスクトップフォルダのパスを得ます。

import macfs, MACFS, os
fsspec_disk, fsspec_desktop = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kDesktopFolderType, 0)
DesktopFolder_path = macfs.FSSpec((fsspec_disk, fsspec_desktop, '')).as_pathname() + os.curdir
print DesktopFolder_path

これを実行すると、わたしの場合、

Performa HD:Desktop Folder:

と表示されました。

同様にして、初期設定フォルダのパスを得るには、

import macfs, MACFS, os
fsspec_disk, fsspec_preference = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kPreferencesFolderType, 0)
PreferencesFolder_path = macfs.FSSpec((fsspec_disk, fsspec_preference, '')).as_pathname() + os.curdir
print PreferencesFolder_path

同様にして、ゴミ箱のパスを得ることができます。

fsspec_disk, fsspec_trash = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kTrashFolderType, 0)
trash_path = macfs.FSSpec((fsspec_disk, fsspec_trash, '')).as_pathname() + os.curdir

ゴミ箱へのパスを使って、ファイルをゴミ箱に入れることができます。

fss, ok = macfs.PromptGetFile('ゴミ箱へ入れるファイルを選んで!')
if ok:
	filepath = fss.as_pathname()
	import findertools
	findertools.move(filepath, trash_path)

InternetConfigの設定からファイルタイプ/クリエータを設定する(ic、macfs)

このページの最初の方にファイルのクリエータとタイプを

fss.SetCreatorType('Pyth', 'TEXT')

で設定しましたが、ファイルの拡張子(「.html」「.bin」など)に合わせてファイルのタイプ/クリエータを設定すると楽なこともあるかと思います。

ブラウザやFTPクライアントソフトには、「ダウンロードしたファイルのクリエータとタイプをInternet Config(インターネット設定機能拡張)での設定にする」機能があります。
それをやってみます。

Internet Configを扱うには、ic モジュールを使うらしいです。

icTest.py
--------------------------
import ic
import macfs

icmap = ic.mapfile('.txt')
fss = macfs.FSSpec('ReadMe')
fss.SetCreatorType(icmap[2],icmap[1])
----------------------------------

この「icTest.py」ファイルと同じフォルダ内に「ReadMe」というファイルがあると、「ReadMe」ファイルをInternet Configで設定されたクリエータ/タイプに設定します。アイコンが変わります。
私の場合、SimpleText のものになります。

ちょっと注釈を書くと...

icmap = ic.mapfile('.txt')
Internet Config の「拡張子等の対応」で'.txt'について設定されたものの情報をタプルで返すようです。
カッコ内はファイル名(文字列)か、Fsspecオブジェクト。
Python Documentationには「存在しないファイルの名前でもいい」みたいなことが書いてあるので(たぶん)、' . 拡張子' と考えてもいいのかもしれません。
ここで得た情報にあるクリエータとタイプを使います。
「拡張子等の対応」で設定されていない拡張子を '〜' に書くと、「icglue error : -666」が出ます。

fss = macfs.FSSpec('ReadMe')
クリエータとタイプを変える対象ファイルとして、実行している'icTest.py'と同じフォルダ内にある'ReadMe'のFsspecオブジェクトを得ています。何かファイルをコピーして'icTest.py'と同じフォルダ内に置き、「ReadMe」という名前に変更してください。
macfs.StandardGetFile() で得てもいいかもしれません。

fss.SetCreatorType(icmap[2],icmap[1])
ic.mapfile('.txt')が返すタプルのうち、3番目([2])がクリエータ、2番目([1])がタイプです。
それで、このように書いてみました。

私は、EasyFtpClientの中に icTest.py みたいなものを書き加えて、ダウンロードしたファイルのクリエータとタイプを設定して、アイコンが表示されるようにしています。


音を鳴らす(MacOS、Snd、macspeech)

アプリケーションの場合、ボタンやメニューの操作などのGUIはもちろん大切ですが、簡単な音を出すこともインターフェイスとして大事だし、また、ただ単に楽しいものです。そんな簡単な音を出す方法を書いておきます。

以下はBeep音(警告音)を出します。

Test1.py
--------------------------
import MacOS
MacOS.SysBeep()
----------------------------------

うーーん。簡単です。「モニタ&サウンド」コントロールパネルで設定した警告音を出します。

もうひとつ。

Test2.py
--------------------------
import Snd
Snd.SysBeep(10000)
----------------------------------

Test1.pyと同じく警告音を出します。Snd.SysBeep()の()内の引数は duration(持続時間?)とありますが、小さな値にして長い警告音を鳴らしても、警告音の全部終わりまで鳴るので、詳しい意味は私にはわかりません。

次にテキストを話すものを。

Test3.py
--------------------------
import macspeech
macspeech.SpeakString("I am speech manager")
----------------------------------

「Speech」コントロールパネルで設定された音声で "I am speech manager" と話します。「Speech Manager」機能拡張がインストールされていないと動作しません。日本語を話すには、「Speech」コントロールパネルで「ひろし」「まさこ」を設定して、macspeech.SpeakString("わたしはスピーチマネージャーです") とすると例の棒読みで話します。

macspeech モジュールから音声の種類を設定したり、pitchやspeedも設定できるようです。

次はリソースの 'snd ' リソースのID 128 を再生します。

Test4.py
--------------------------
import sys
import Res
import EasyDialogs
sndID = 128
if sys.argv[0][-3:] == '.py':
	RSRC_NAME= sys.argv[0][:-3] + '.rsrc'
else:
	RSRC_NAME= sys.argv[0] + '.rsrc'

try:
	sndHandle = Res.GetResource('snd ', sndID)
except Res.Error:
	try:
		print "open rsrc file"
		Res.FSpOpenResFile(RSRC_NAME, 1)
		sndHandle = Res.GetResource('snd ', sndID)
	except Res.Error:
		EasyDialogs.Message("Cannot open "+RSRC_NAME)
		sys.exit()
"""ここまでは、Test4.pyファイルを実行しているのなら 'Test4.rsrc'リソースファイルを開いて
実行し、すでにアプレットになっていた場合には 'snd 'リソースから読み出せ、
ということをやっています。"""
ch = Snd.SndNewChannel(0,0,None)
ch.SndPlay(sndHandle, 0)
----------------------------------

以下は 'snd 'リソースの作り方です。知らない人のために。

Test4.pyと同じフォルダ内に 'Test4.rsrc' リソースファイルを作ります。ResEditを開いて、Fileメニューから「New...」を選び、「Test4.rsrc」という名前でTest4.pyと同じフォルダ内にファイルを作ります。
Resourceメニューから「Create New Resource」を選ぶとたくさんのリソースタイプから選択するダイアログが出てくるので、'snd ' を選びます。
'snd ID = 128 from Test4.rsrc ' というウィンドウが作られますが、これを閉じます。
'snds from Test4.rsrc' ウィンドウが最前面に出て来ます。この中のID 128を選択して、Editメニューから「Cut」を選んで、消して下さい。
snd メニューから「Record New Sound...」を選ぶと録音/再生などのボタンのダイアログが表示されるので、録音ボタンを押し、「モニタ&サウンド」コントロールパネルで設定された経路から録音して下さい。私は「内蔵マイク」を選んでおいて、適当に叫びました。
「停止」ボタンを押し、再生してみたりして、これでいいなら「保存」ボタンを押します。
すると、ID 128 としてリソースができますので、保存してResEditを終了します。
上の Test4.py を実行すると、録音したID 128 が再生されます。

Snd.SndNewChannel、Snd.SndPlay の引数の詳しいことは私にはわかりません。
pydoc モジュールで __doc__ を読んでみるとか、Cのソースを読んでみたり、Inside Macintosh を読めばわかるのかも...私にはよくわかりませんでした。


プログレスバーを表示する(EasyDialogs)

Macintosh Library Modulesを訳していて、プログレスバーの使い方がわかりました。

簡単な例

bar1.py
--------------------------------------------------
import EasyDialogs

bar = EasyDialogs.ProgressBar("Test Bar",100,"Working...")

for i in range(101):
	bar.inc()
--------------------------------------------------
bar = EasyDialogs.ProgressBar("Test Bar",100,"Working...")
プログレスバーを持ったウィンドウを表示します。"Test Bar"はタイトルの文字列、100はバーの進行が停止するときの値、"Working..."はバーの上に表示されるラベル(文字列)です。
bar.inc()
バーの値を1だけ増やします。bar.inc(n)でnだけ増やすこともできます。dec()メソッドもあって、減らすこともできます。

bar1.pyを実行すると、以下のようなウィンドウが表示されて、右端に達すると終了します。

bar1.pyの実行

バーのラベルを変更

バーが増えていくごとにラベルも変更してみます。

bar2.py
--------------------------------------------------
import EasyDialogs

bar = EasyDialogs.ProgressBar("Test Bar",100,"Working...")

for i in range(101):
	bar.label("%s 回目 値:%d" % (i, bar.curval))
	bar.inc()
--------------------------------------------------
bar.label("%s 回目 値:%d" % (i, bar.curval))
今度は、このメソッドでラベルの文字列を変更します。bar.curvalはバーの現在の値です。

下が実行例です。

bar2.pyの実行

床屋さんのぐるぐる看板(?)

MacPython2.2以降では不定量プログレスインジケータが使えるようになりました。"不定量プログレスインジケータ"はぐるぐる回るバーです。普通の温度計型のバーは"定量プログレスインジケータ"というそうです。

bar3.py
--------------------------------------------------
bar = EasyDialogs.ProgressBar("Test Bar",100,"Working...")

for i in range(101):
	bar.label("%s 回目 値:%d" % (i, bar.curval))
	bar.inc()

bar.set(0,0)
for i in range(101):
	bar.label("%s 回目 値:%d" % (i, bar.curval))
	bar.inc()
--------------------------------------------------
bar.set(0,0)
set(val, max)で現在値をvalにし、バーの最大値をmaxにします。バーの最大値が0以下だと不定量プログレスインジケータになるそうです。初めからbarを
bar=EasyDialogs.ProgressBar("Test Bar",0,"Working...")
で定義してもいいんですが。。。

下が実行例です。最大値を0に設定しているせいか、値は0のままです。

bar3.pyの実行

クリップボードの操作(Scrap、Res)

トップページAddQuote2Clip.pyのことを書いておきます。話題がなくなってきたので。。。(^ ^;

"""クリップボードのTEXTの行頭にquote文字を加える。
"""

import string
import EasyDialogs
import Scrap
import Res
"""MacPython2.1以降をお使いの場合は、上2行の代わりに
from Carbon import Scrap
from Carbon import Res
を使ってください。"""

#quote文字列の初期設定
QUOTE = '>'

def addQuote(Singleline):
	"""文字列Singlelineを受け取り、quoteStringを文字列の初めに
	加えて返す関数"""
	return quoteString + Singleline

#Handleを設定(Inside Macintosh:Toolbox Essential参照)
handle = Res.Handle('')

#クリップボードの内容のうち'TEXT'の”文字列の長さ”である[0]を取得
stuff = Scrap.GetScrap(handle,'TEXT')[0]
if stuff > 0:
	#”文字列の長さ”が0より大きいとき(クリップボードにテキストがあるとき)
	#クリップボードの文字列を取得
	stuff_data = handle.data
	if stuff_data != '':
		#いらないかもしれないけど、クリップボード文字列が''(空白)でなければ...
		#quoteとして使う文字列を尋ねる。
		quoteString = EasyDialogs.AskString("Input Quote String", QUOTE)
		if quoteString != None:
			#quote文字列が入力されたら
			#クリップボード文字列を行で分けてリストにする
			lines = string.split(stuff_data,'\r')
			#各行の文字列(リストの各オブジェクト)にquote文字列を加える
			quoted_list = map(addQuote, lines)
			#各行の文字列(リストの各オブジェクト)に改行を加えて繋げる
			quoted_stuff = string.join(quoted_list, '\r')
			#クリップボードの内容を初期化
			Scrap.ZeroScrap()
			#クリップボードに文字列を登録
			Scrap.PutScrap('TEXT', quoted_stuff)
			#「加えたよ」のダイアログ
			EasyDialogs.Message("Added '%s' to Clipboard TEXT" % quoteString)
		else:
			#quote文字列が入力されてなかったら
			EasyDialogs.Message('Input Quote String !!')
	else:
		#クリップボード文字列が空白だったら
		EasyDialogs.Message('No TEXT in Clipboard!')
else:
	#クリップボードに'TEXT'がなかったら
	EasyDialogs.Message('No TEXT Stuff in Clipboard!')

<▲このページのTOPへ>
MacPythonについてのページ(よ)TOPへ

by ©Hioryuki Yoshimura, 2002-2004.
Last modified at 2005/8/20