質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
87.20%
Flask

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

OAuth

OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Python

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

受付中

FlaskでOAuth認証時に発生するUnicodeDecodeErrorを解決したい

masty0000
masty0000

総合スコア0

Flask

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

OAuth

OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Python

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

1回答

0評価

0クリップ

1485閲覧

投稿2018/12/30 07:53

編集2022/01/12 10:55

前提・実現したいこと

PythonのWEBフレームワークFlaskを用いて、とある書籍を参考に、質問箱アプリを開発しています。
ログイン機能として、Twitterのアカウントを用いたOAuth認証を実装しようとしています。

リクエスト・トークンを取得し、その後リクエスト・トークンを元にアクセス・トークンを取得する段階で下記のようなエラーが発生しました。
(WEB画面上で言うと、ユーザーに対し、アプリがユーザー情報を利用することを許可する画面から、許可後、コールバックURLへリダイレクトするところでエラーが発生)

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

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1490: ordinal not in range(128)

表示されたメッセージの全文としては、以下の通りです。

(flaskApp3) mas-mac-pc% flask run * Serving Flask app "app.py" (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 916-800-986 127.0.0.1 - - [30/Dec/2018 16:11:21] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [30/Dec/2018 16:11:25] "GET /oauth/twitter HTTP/1.1" 302 - 127.0.0.1 - - [30/Dec/2018 16:11:28] "GET /oauth/twitter/callback?provider=twitter&oauth_token={非公開}&oauth_verifier={非公開} HTTP/1.1" 500 - Traceback (most recent call last): File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__ return self.wsgi_app(environ, start_response) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app response = self.handle_exception(e) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception reraise(exc_type, exc_value, tb) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise raise value File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise raise value File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/Users/Mas/Python/flask/flaskApp3/app.py", line 123, in oauth_callback data={'oauth_verifier': request.args['oauth_verifier']} # ここがエラーの原因 File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/rauth/service.py", line 359, in get_auth_session **kwargs) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/rauth/service.py", line 332, in get_access_token process_token_request(r, decoder, key_token, key_token_secret) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/rauth/service.py", line 20, in process_token_request data = decoder(r.content) File "/Users/Mas/.local/share/virtualenvs/flaskApp3-s8OM8UNK/lib/python3.7/site-packages/rauth/utils.py", line 26, in parse_utf8_qsl for k, v in dict(parse_qsl(s)).items(): # pragma: no cover File "/anaconda3/lib/python3.7/urllib/parse.py", line 683, in parse_qsl qs, _coerce_result = _coerce_args(qs) File "/anaconda3/lib/python3.7/urllib/parse.py", line 123, in _coerce_args return _decode_args(args) + (_encode_result,) File "/anaconda3/lib/python3.7/urllib/parse.py", line 107, in _decode_args return tuple(x.decode(encoding, errors) if x else '' for x in args) File "/anaconda3/lib/python3.7/urllib/parse.py", line 107, in <genexpr> return tuple(x.decode(encoding, errors) if x else '' for x in args) UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1490: ordinal not in range(128)

該当のソースコード

app.py

from flask import Flask, redirect, url_for, session, request, render_template from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import UserMixin, LoginManager, login_user, logout_user, current_user, login_required from datetime import datetime from rauth import OAuth1Service app = Flask(__name__) app.secret_key = 'xxxxxxxxxx' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://localhost/testdb" db = SQLAlchemy(app) login_manager = LoginManager(app) login_manager.login_view = 'index' migrate = Migrate(app, db) service = OAuth1Service( name='twitter', consumer_key='XXXXXXXXXX', consumer_secret='XXXXXXXXXX', request_token_url='https://api.twitter.com/oauth/request_token', authorize_url='https://api.twitter.com/oauth/authorize', access_token_url='https:/api.twitter.com/oauth/access_token', base_url='https://api.twitter.com/1.1' ) # Userモデル class User(UserMixin, db.Model): # テーブル定義 id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True) description = db.Column(db.String(1204), index=True, unique=True) user_image_url = db.Column(db.String(1204), index=True, unique=True) date_published = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) twitter_id = db.Column(db.String(64), nullable=False, unique=True) def __repr__(self): return '<User %r>' % self.username @app.route('/') def index(): return render_template('index.html') @app.route('/logout') def logout(): logout_user() return redirect(url_for('index')) @app.route('/oauth/twitter') def oauth_authorize(): if not current_user.is_anonymous: return redirect(url_for('index')) else: request_token = service.get_request_token( params={'oauth_callback': url_for('oauth_callback', provider='twitter', _external=True)} ) session['request_token'] = request_token return redirect(service.get_authorize_url(request_token[0])) @app.route('/oauth/twitter/callback') def oauth_callback(): request_token = session.pop('request_token') oauth_session = service.get_auth_session( request_token[0], request_token[1], method='GET', # 自分で追加 data={'oauth_verifier': request.args['oauth_verifier']} # ここがエラー発生 ) profile = oauth_session.get('account/verify_credentials.json').json() twitter_id = str(profile.get('id')) username = str(profile.get('name')) description = str(profile.get('description')) profile_image_url = str(profile.get('profile_image_url')) user = db.session.query(User).filter(User.twitter_id==twitter_id).first() if user: user.twitter_id = twitter_id user.username = username else: user = User(twitter_id=twitter_id, username=username, description=description, user_image_url=profile_image_url) db.session.add(user) db.session.commit() login_user(user, True) return redirect(url_for('index')) @login_manager.user_loader def load_user(id): return User.query.get(int(id))

試したこと

エラーメッセージからasciiでデコードしているようなので、
以下を実行してみましたが、環境のエンコーディングはutf-8でした。

>>> import locale >>> print(locale.getpreferredencoding()) UTF-8 >>> import sys >>> print(sys.getdefaultencoding()) utf-8

また、エラーメッセージからparse.pyで例外が発生しているようだったので、
parse.pyの中身を見てみたりしてみましたが、いまいちわからず・・・

補足情報(FW/ツールのバージョンなど)

・OS:OS X EI Captain(Version 10.11.6)
・Python:3.7.0
・Flask:1.0.2
・pipenv:version 2018.11.14

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

can110
can110

2018/12/30 08:47

「request\.args\['oauth_verifier'\]」の型は何(strまたはbytes?)でしょうか
masty0000
masty0000

2018/12/30 09:50

確認したところ、strでした。
hayataka2049
hayataka2049

2018/12/30 09:52

「該当のソースコード」先頭に import sys print\(sys\.version\) と書いて実行した場合の結果は何になりますか
hayataka2049
hayataka2049

2018/12/30 09:56

すみません、質問文の3\.7という記載を見落としていました。スルーして構いません
hayataka2049
hayataka2049

2018/12/30 09:56

すみません、質問文の3\.7という記載を見落としていました。スルーして構いません
masty0000
masty0000

2018/12/30 10:00

ありがとうございます。 念の為再度確認してみましたが、以下の通りでした。 3\.7\.0 \(default, Jun 28 2018, 07:39:16\) \[Clang 4\.0\.1 \(tags/RELEASE_401/final\)\]

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Flask

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

OAuth

OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Python

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