🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

6577閲覧

Flask内でwin32comを扱う

mo256man

総合スコア43

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/02/18 12:15

実現したいこと

win32comでoutlookのメールデータを取得してFlaskにてブラウザ上で表示させたいと考えています。

まず、以下は、Flaskを使わない、メールのサブジェクトを取得し出力するプログラムです。

Python

1import win32com.client 2 3outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") 4folder = outlook.GetDefaultFolder(6) # 受信トレイ決め打ち 5 6def getMail(): 7 mail_data = [] 8 mails = folder.Items 9 for mail in mails: 10 title = mail.Subject 11 mail_data.append(title) 12 return mail_data 13 14def main(): 15 mail_data = getMail() 16 print(mail_data) 17 18if __name__ == "__main__": 19 main()

ところが、これをFlaskでおこなおうとするとエラーになってしまいました。

Python

1import win32com.client 2from flask import Flask, render_template 3 4outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") 5folder = outlook.GetDefaultFolder(6) # 受信トレイ決め打ち 6app = Flask(__name__) 7 8def getMail(): 9 mail_data = [] 10 mails = folder.Items 11 for mail in mails: 12 title = mail.Subject 13 mail_data.append(title) 14 return mail_data 15 16@app.route("/") 17def main(): 18 mail_data = getMail() 19 return render_template("index.html", mail_data = mail_data) 20 21if __name__ == "__main__": 22 app.run(debug=True)

どこをどのように直したらよろしいでしょうか。

発生している問題・エラーメッセージ

上記コードでのエラー

AttributeError: GetDefaultFolder.Items

outlookやfolderの定義を関数内に入れたときのエラー

pywintypes.com_error: CoInitializeは呼び出されていません

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/02/20 01:50

flaskはスレッドを使います。 COMはスレッドごとにCoInitialize(CoInitializeEx)を呼び出す必要があります。 私は使ったことありませんが、pythoncomもimportしてpythoncom.CoInitializeを各スレッドで呼んでみてはどうでしょうか? import pythoncom ... pythoncom.CoInitialize() outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") ... def getMail():   pythoncom.CoInitialize() # 全角空白でインデント空けてます   mail_data = [] 試してないので参考情報です。
mo256man

2021/02/22 11:00

ヒントありがとうございます。 私のほうでも収穫がありましたので別途自己解決欄にて報告いたします。
guest

回答1

0

自己解決

以下のサイトのやり方で動かすことができました。
com_error at / (-2147221008, 'CoInitialize は呼び出されていません。', None, None)

すなわち、

Python

1from win32com.client import gencache, Dispatch 2import pythoncom 3 4class Outlook(): 5 def __init__(self, visible=False): 6 pythoncom.CoInitialize() 7 self._app = Dispatch("Outlook.Application").GetNamespace("MAPI") 8 # self._app.Visible = visible # 元サイトにあったこれは無くてよい 9 10 @property 11 def app(self): 12 return self._app 13 14 def quit(self): 15 self.app.Quit() 16 pythoncom.CoUninitialize()

を用意しておき、

Python

1def getMail(): 2 outlook = Outlook().app # 追加 3 mail_data = [] 4 mails = folder.Items 5 for mail in mails: 6 title = mail.Subject 7 mail_data.append(title) 8 outlook().quit # 追加 9 return mail_data

と、Outlookへのアクセスの前後で CoInitialize および CoUninitialize を呼び出すのです、
dameoさんが示してくださったサンプルコードの中にCoUninitializeがなかったのでこの一文を消してみたところ、それでも正しく動きました。
ファイルはオープンしたらクローズしましょうというのがこの世界のお作法でもありますし、CoUninitialize は付けたほうがよさそうですね。

dameoさん、どうもありがとうございました。

投稿2021/02/24 14:30

mo256man

総合スコア43

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問