はい!今やってます!

Work Pertly, Live Idly

pipenvでmysqlclientをinstallしようとするとエラーになる時の対処

pipenv install mysqlclient

でmysqlclientをinstallしようとするとエラーになった。

➜  hogehoge git:(master) ✗ pipenv install mysqlclient
Installing mysqlclient…
Adding mysqlclient to Pipfile's [packages]…
✔ Installation Succeeded
Installing dependencies from Pipfile.lock (d08757)…
An error occurred while installing mysqlclient==1.4.2.post1 --hash=sha256:425e733b05e359a714d6007c0fc44582be66b63e5a3df0a50949274ae16f4bc6 --hash=sha256:62e4770b6a797b9416bcf70488365b7d6b9c9066878108499c559293bb464380 --hash=sha256:f257d250f2675d0ef99bd318906f3cfc05cef4a2f385ea695ff32a3f04b9f9a7! Will try again.
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 26/26 — 00:00:05
Installing initially failed dependencies…
[pipenv.exceptions.InstallError]:   File "/usr/local/Cellar/pipenv/2018.11.26_2/libexec/lib/python3.7/site-packages/pipenv/core.py", line 1992, in do_install
[pipenv.exceptions.InstallError]:       skip_lock=skip_lock,
[pipenv.exceptions.InstallError]:   File "/usr/local/Cellar/pipenv/2018.11.26_2/libexec/lib/python3.7/site-packages/pipenv/core.py", line 1253, in do_init
[pipenv.exceptions.InstallError]:       pypi_mirror=pypi_mirror,
[pipenv.exceptions.InstallError]:   File "/usr/local/Cellar/pipenv/2018.11.26_2/libexec/lib/python3.7/site-packages/pipenv/core.py", line 859, in do_install_dependencies
[pipenv.exceptions.InstallError]:       retry_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
[pipenv.exceptions.InstallError]:   File "/usr/local/Cellar/pipenv/2018.11.26_2/libexec/lib/python3.7/site-packages/pipenv/core.py", line 763, in batch_install
[pipenv.exceptions.InstallError]:       _cleanup_procs(procs, not blocking, failed_deps_queue, retry=retry)
[pipenv.exceptions.InstallError]:   File "/usr/local/Cellar/pipenv/2018.11.26_2/libexec/lib/python3.7/site-packages/pipenv/core.py", line 681, in _cleanup_procs
[pipenv.exceptions.InstallError]:       raise exceptions.InstallError(c.dep.name, extra=err_lines)
[pipenv.exceptions.InstallError]: ['Collecting mysqlclient==1.4.2.post1 (from -r /var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pipenv-4phml1tv-requirements/pipenv-ii2ivfrb-requirement.txt (line 1))', '  Using cached https://files.pythonhosted.org/packages/f4/f1/3bb6f64ca7a429729413e6556b7ba5976df06019a5245a43d36032f1061e/mysqlclient-1.4.2.post1.tar.gz', 'Building wheels for collected packages: mysqlclient', '  Building wheel for mysqlclient (setup.py): started', "  Building wheel for mysqlclient (setup.py): finished with status 'error'", '  Running setup.py clean for mysqlclient', 'Failed to build mysqlclient', 'Installing collected packages: mysqlclient', '  Running setup.py install for mysqlclient: started', "    Running setup.py install for mysqlclient: finished with status 'error'"]
[pipenv.exceptions.InstallError]: ['ERROR: Complete output from command /Users/wuzzy/git/samurai/senews-crawler/.venv/bin/python3.7 -u -c \'import setuptools, tokenize;__file__=\'"\'"\'/private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-install-fz26c_69/mysqlclient/setup.py\'"\'"\';f=getattr(tokenize, \'"\'"\'open\'"\'"\', open)(__file__);code=f.read().replace(\'"\'"\'\\r\\n\'"\'"\', \'"\'"\'\\n\'"\'"\');f.close();exec(compile(code, __file__, \'"\'"\'exec\'"\'"\'))\' bdist_wheel -d /private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-wheel-jvsliezu --python-tag cp37:', '  ERROR: running bdist_wheel', '  running build', '  running build_py', '  creating build', '  creating build/lib.macosx-10.14-x86_64-3.7', '  creating build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/_exceptions.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/compat.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/connections.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/converters.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/cursors.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/release.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  copying MySQLdb/times.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '  creating build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/CLIENT.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/CR.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/ER.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/FIELD_TYPE.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  copying MySQLdb/constants/FLAG.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '  warning: build_py: byte-compiling is disabled, skipping.', '  ', '  running build_ext', "  building 'MySQLdb._mysql' extension", '  creating build/temp.macosx-10.14-x86_64-3.7', '  creating build/temp.macosx-10.14-x86_64-3.7/MySQLdb', "  clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -Dversion_info=(1,4,2,'post',1) -D__version__=1.4.2.post1 -I/usr/local/Cellar/mysql/5.7.20/include/mysql -I/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c MySQLdb/_mysql.c -o build/temp.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.o", '  clang -bundle -undefined dynamic_lookup -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk build/temp.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.o -L/usr/local/Cellar/mysql/5.7.20/lib -lmysqlclient -lssl -lcrypto -o build/lib.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.cpython-37m-darwin.so', '  ld: library not found for -lssl', '  clang: error: linker command failed with exit code 1 (use -v to see invocation)', "  error: command 'clang' failed with exit status 1", '  ----------------------------------------', '  ERROR: Failed building wheel for mysqlclient', '    ERROR: Complete output from command /Users/wuzzy/git/samurai/senews-crawler/.venv/bin/python3.7 -u -c \'import setuptools, tokenize;__file__=\'"\'"\'/private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-install-fz26c_69/mysqlclient/setup.py\'"\'"\';f=getattr(tokenize, \'"\'"\'open\'"\'"\', open)(__file__);code=f.read().replace(\'"\'"\'\\r\\n\'"\'"\', \'"\'"\'\\n\'"\'"\');f.close();exec(compile(code, __file__, \'"\'"\'exec\'"\'"\'))\' install --record /private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-record-6o8_smzs/install-record.txt --single-version-externally-managed --compile --install-headers /Users/wuzzy/git/samurai/senews-crawler/.venv/bin/../include/site/python3.7/mysqlclient:', '    ERROR: running install', '    running build', '    running build_py', '    creating build', '    creating build/lib.macosx-10.14-x86_64-3.7', '    creating build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/_exceptions.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/compat.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/connections.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/converters.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/cursors.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/release.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    copying MySQLdb/times.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb', '    creating build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/CLIENT.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/CR.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/ER.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/FIELD_TYPE.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    copying MySQLdb/constants/FLAG.py -> build/lib.macosx-10.14-x86_64-3.7/MySQLdb/constants', '    warning: build_py: byte-compiling is disabled, skipping.', '    ', '    running build_ext', "    building 'MySQLdb._mysql' extension", '    creating build/temp.macosx-10.14-x86_64-3.7', '    creating build/temp.macosx-10.14-x86_64-3.7/MySQLdb', "    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -Dversion_info=(1,4,2,'post',1) -D__version__=1.4.2.post1 -I/usr/local/Cellar/mysql/5.7.20/include/mysql -I/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c MySQLdb/_mysql.c -o build/temp.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.o", '    clang -bundle -undefined dynamic_lookup -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk build/temp.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.o -L/usr/local/Cellar/mysql/5.7.20/lib -lmysqlclient -lssl -lcrypto -o build/lib.macosx-10.14-x86_64-3.7/MySQLdb/_mysql.cpython-37m-darwin.so', '    ld: library not found for -lssl', '    clang: error: linker command failed with exit code 1 (use -v to see invocation)', "    error: command 'clang' failed with exit status 1", '    ----------------------------------------', 'ERROR: Command "/Users/wuzzy/git/samurai/senews-crawler/.venv/bin/python3.7 -u -c \'import setuptools, tokenize;__file__=\'"\'"\'/private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-install-fz26c_69/mysqlclient/setup.py\'"\'"\';f=getattr(tokenize, \'"\'"\'open\'"\'"\', open)(__file__);code=f.read().replace(\'"\'"\'\\r\\n\'"\'"\', \'"\'"\'\\n\'"\'"\');f.close();exec(compile(code, __file__, \'"\'"\'exec\'"\'"\'))\' install --record /private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-record-6o8_smzs/install-record.txt --single-version-externally-managed --compile --install-headers /Users/wuzzy/git/samurai/senews-crawler/.venv/bin/../include/site/python3.7/mysqlclient" failed with error code 1 in /private/var/folders/1g/p4qmy_j56hb2rdn9mskfv74m0000gn/T/pip-install-fz26c_69/mysqlclient/']
ERROR: ERROR: Package installation failed...
  ☤  ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/1 — 00:

結論opensslのPATHを追加してやると解決する。

brew info openssl

すると以下のような案内がでるので、

SSL/TLS cryptography library
https://openssl.org/
/usr/local/Cellar/openssl/1.0.2r (1,795 files, 12.1MB)
  Poured from bottle on 2019-04-02 at 10:21:56
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/openssl.rb
==> Caveats
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

openssl is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.

If you need to have openssl first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl/include"

For pkg-config to find openssl you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"

上記の案内の通りにPATHを通してやると問題なくインストールできる。

➜  hogehoge git:(master) ✗ pipenv install mysqlclient
Installing mysqlclient…
Adding mysqlclient to Pipfile's [packages]…
✔ Installation Succeeded
Installing dependencies from Pipfile.lock (d08757)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 26/26 — 00:00:02
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

TwitterのOAuthの流れを整理しておく

これはなに

SPAでTwitterのOAuthを実装しようとしていたのだけど、 Twitter Developerで取得できる Consumer API key Consumer API key secret このあたりをどうやって隠蔽するのかというのを考えていたらよくわからなくなってきたので、 基礎知識としてサーバーサイドでTwitter認証する時の流れを整理しておく。 ※Consumer API keyは過去にConsumer tokenと呼ばれていたらしい。今は名前が変わった。

TwitterのOAuthの流れ

TwitterのDeveloperアカウントを設定して払い出されるConsumer API key,Consumer API key secretを使って、 任意のユーザーがAPIを呼び出すためのaccess_token,access_token_secretを得るのがゴール

流れは下記のとおり

  1. Consumer API key,Consumer API key secretを使ってrequest_tokenを得る
  2. https://api.twitter.com/oauth/authenticate?oauth_token={$request_token}に遷移
  3. oauth_tokenoauth_verifierを使ってアクセストークンを発行する

1. request_tokenを得る

まずはrequest_tokenを得る これはConsumer API key,Consumer API key secretを使って、oauth/request_tokenにPOSTリクエストを投げると取得することができる。 ちなみにoauth_callbackというパラメーターにTwitterDeveloperのcallbackに指定したURLのいずれかを設定してリクエストを送信する必要がある。

2. request_token認証を使って認証画面に遷移する

前の手順で得られたrequest_tokenoauth_tokenパラメーターにつけて

https://api.twitter.com/oauth/authenticate?oauth_token={$request_token}

というURLにアクセスすると、Twitter側の提供されるログイン画面に遷移する。 ※oauth_token={$request_token}がすでに気持ち悪いが気にしない。

3. アクセストークンを発行する

連携画面でログインが成功すると、callbackで指定したURLに遷移する。 遷移時のGETパラメーターに

oauth_token={$oauth_token}&oauth_verifier={$oauth_verifier}

という形でパラメーターが付与されるので、 Consumer API key,Consumer API key secret,oauth_token, oauth_verifierをつかって oauth/access_tokenに対してPOSTのリクエストを投げる。 するとaccess_tokenaccess_token_secretが得られる。

複雑なように見えるが実際は三度の通信が走るだけになっている。

※なおTwitterのOAuthはシグネチャを生成して、リクエストに含める必要がある。 リクエストパラメーターやtokenをひとまとめにしたデータを先性して、パラメーターを送信し整合性チェックを行う設計らしい。