ローカルで作成した Django アプリケーションを Ubuntu の本番環境へ反映する

Mac のローカル環境で作成した Django プロジェクトをさくらの VPS で用意した Ubuntu 環境へ反映する際の流れをメモしています。

下記が完了していることを想定しています。

  • Web サーバーの設定が完了済み(筆者は Nginx を使用)
  • 仮想環境を作るディレクトリが決めてある
  1. データベースを本番環境にコピーする
    • ローカル環境での作業
    • 本番環境での作業
  2. ローカル環境のパッケージを本番環境で再現
    • requirements.txt の作成
    • requirements.txt を本番環境へコピー
    • 本番環境で Python 仮想環境を作成
    • requirements.txt によるパッケージインストール
  3. gunicorn のインストール
  4. settings.py の編集
    • ファイルを分割する必要性
    • 開発環境の runserver 実行時に settings_dev.py を指定
    • settings.py(本番環境用)の編集
  5. Django ソースコードを本番環境に配置
    • 本番環境への git のインストール
    • リモートリポジトリから本番環境へファイルをコピー
  6. データベースのログイン情報をサーバーの環境変数に記述
  7. 静的ファイルの配置

1. データベースを本番環境にコピーする

検証環境で準備したデータベース、テーブル、そしてデータを本番環境でも反映します。

ここはうまくやれば一行スクリプト書いて終了する方法もある様ですが、色々とエラーが出て逆にめんどくさそうだったのでステップバイステップでやっていきます。

ローカル環境での作業

まずローカル環境でコマンド「mysqldump データベース名 > dump.txt」を実行し、dump ファイルを作成します。

% mysqldump graffuhs > dump.txt                                                              
%

それを FTP か何かで本番環境へアップロードします。

本番環境での作業

本番環境に接続し、本番環境の MySQL でデータベースを作成します。

mysql> create database データベース名;

そしてコマンド「sudo mysql データベース名 < dump.txt」を実行します。

$ sudo mysql データベース名 < dump.txt
$

これで本番環境の MySQL にもローカル環境と同じデータベース、テーブル、そしてデータがコピーされました。

2. ローカル環境のパッケージを本番環境で再現

ローカル環境の Python 関連パッケージを本番環境でも再現するため、ローカル環境で requirements.txt ファイルを作成し、それを元に本番環境でパッケージインストールをさせます。

requirements.txt の作成

ローカル環境の Python 仮想環境へ移り、コマンド「pip freeze > requirements.txt」を実行します。

% pip freeze > requirements.txt

requirements.txt を本番環境へコピー

コマンド「scp requirements.txt 本番環境のユーザー名@本番環境のホスト名(もしくは IP アドレス):保存先のディレクトリ」を実行します。

だいぶ長いですが下記の例だとすると。。。

  • 本番環境のユーザー名: vpsadmin
  • 本番環境のホスト名: xx1-234-56789.vs.sakura.ne.jp
  • 保存先のディレクトリ: /var/www/example.com/html

下記の様になります。

scp requirements.txt vpsadmin@xx1-234-56789.vs.sakura.ne.jp:/var/www/example.com/html

無事本番環境に requirements.txt がコピーされました。

$ ls
pythonvenv  requirements.txt

本番環境で Python 仮想環境を作成

本番環境のディレクトリへ移動し、Python の仮想環境を作成します。

$ python3.9 -m venv pythonvenv
$ ls
pythonvenv

requirements.txt によるパッケージインストール

本番環境の Python 仮想環境に入った状態で、コマンド「pip install -r requirements.txt」を実行します。

(pythonvenv) $ pip install -r requirements.txt

すると requirements.txt の内容を元に Django を含めローカル環境で使っていたものと同じパッケージがインストールされます。

3. gunicorn のインストール

本番環境でのみ必要となるものとして、アプリケーションサーバーがあります。今回は gunicorn を使います。

Python 仮想環境内でアプリケーションサーバーの gunicorn をインストールします。

(pythonvenv) $ pip install gunicorn

4. settings.py の編集

ファイルを分割する必要性

settings.py は本番環境と開発環境で内容が異なる部分が出てくるので、下記の様にファイルを分ける必要があります。(ファイル名は任意)

  • settings_common.py:開発環境と本番環境で共通の部分を記述
  • settings.py:本番環境でのみ適用する部分を記述
  • settings_dev.py:開発環境でのみ適用する部分を記述

settings.py と settings_dev.py それぞれに「from .settings_common import *」と記述し、共通部分を settings_common.py から読み込む様設定します。

開発環境の runserver 実行時に settings_dev.py を指定

runserver 実行時、デフォルトでは settings.py が設定ファイルとして読み込まれますが、今後開発環境(ローカル環境)では settings_dev.py を使う必要があります。

そのため、今後開発環境で runserver を実行する際は settings_dev.py を「runserver --settings=プロジェクトディレクトリ名.settings_dev」の形式で渡して実行します。

(inmybag) % python manage.py runserver --settings=some_project.settings_dev

settings.py(本番環境用)の編集

DEBUG の変更

False に変更

DEBUG = False

ALLOWED_HOSTS の変更

ドメイン名を設定。

ALLOWED_HOSTS = ['example.com']

Web サーバーで www.example.com から example.com のリダイレクトを行っていれば example.com のみを設定するだけで大丈夫。

静的ファイルの本番環境での配置場所

STATIC_ROOT = '/var/www/examlpe.com/html/static'

5. Django ソースコードを本番環境に配置

本番環境への git のインストール

本番環境でコマンド「sudo apt update」を実行しパッケージリストを更新、その後「sudo apt install git」で git をインストールします。

$ sudo apt update
$ sudo apt install git
Reading package lists... Done
Building dependency tree       
Reading state information... Done
git is already the newest version (1:2.25.1-1ubuntu3.1).
git set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.

リモートリポジトリから本番環境へファイルをコピー

プロジェクトフォルダをリポジトリに設定しているので、プロジェクトフォルダを配置したい場所へ移動した上で git clone を実行します。

$ git clone https://github.com/ユーザー名/リポジトリ名.git

これで本番環境にもプロジェクトフォルダがコピーされました。

今後作業する際は何かにつけて「pkill gunicorn」で gunicorn を終わらせた方が良いです。エラーが起きた時にいくらコードを修正しても治らないまま数時間経って、「pkill gunicorn」一発で治ったこともありました。

6. データベースのログイン情報をサーバーの環境変数に記述

MySQL のデータベースを使用していて、settings.py ではユーザー名とパスワードを環境変数から取る様に設定しています。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'データベース名',
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '',
        'PORT': '',
    }
}

そのため、サーバーの環境変数として記述します。ホームディレクトリの .bashrc ファイルの最下部に下記を追加しました。

export DB_USER='ユーザー名'
export DB_PASSWORD='パスワード'

7. 静的ファイルの配置

コマンド「python manage.py collectstatic」を実行し、settings.py で STATIC_ROOT に設定したパスに静的ファイルを集約します。

$ python manage.py collectstatic

これでとりあえず本番環境でも動くと思います。

Mac「brew install mysqlclient」でエラー「pip install mysql で成功」

環境

OS: macOS Big Sur バージョン 11.2.2
Python: Python 3.8.3

brew install mysqlclient でエラー

Python 仮想環境で「brew install mysqlclient」を実行したら下記のエラーが発生しました。結論から言うと「pip install mysqlclient」の間違いだったことに後で気づきました。

が、それに気づく前に「pip install mysql」を実行して無事解決したので書いておきます。

エラーログ

==> Searching for similarly named formulae...
These similarly named formulae were found:
mysql-client                                                                                  mysql-client@5.7
To install one of them, run (for example):
  brew install mysql-client
Error: No available formula or cask with the name "mysqlclient".
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.

とりあえず一番初めのエラー「Error: No available formula or cask with the name "mysqlclient".」が気になる。

調べてみると、「pip install mysql」を実行してその後に「pip install mysqlclient」を実行するという書き込みを発見。

ただ実際は「pip install mysql」だけで成功しました。

pip install mysql で成功

仮想環境内でコマンド「pip install mysql」を実行。

(venv) % pip install mysql
Collecting mysql
  Downloading https://files.pythonhosted.org/packages/bf/5f/b574ac9f70811df0540e403309f349a8b9fa1a25d3653824c32e52cc1f28/mysql-0.0.2.tar.gz
Collecting mysqlclient (from mysql)
  Downloading https://files.pythonhosted.org/packages/3c/df/59cd2fa5e48d0804d213bdcb1acb4d08c403b61c7ff7ed4dd4a6a2deb3f7/mysqlclient-2.0.3.tar.gz (88kB)
     |████████████████████████████████| 92kB 5.7MB/s 
Installing collected packages: mysqlclient, mysql
  Running setup.py install for mysqlclient ... done
  Running setup.py install for mysql ... done
Successfully installed mysql-0.0.2 mysqlclient-2.0.3
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) %

「pip install mysql」で mysqlclient もカバーされている?

ログをみるとちらほら「mysqlclient」について書かれているのが見えると思います。

そして「Successfully installed mysql-0.0.2 mysqlclient-2.0.3」の一文も。これってストレートに「mysql と mysqlclient が無事インストールされました。」ってことですよね?

% pip install mysqlclient

なので python を立ち上げて「import MySQLdb」を実行してみたら特にエラーも出ず。

「pip install mysqlclient」を実行しても何も変わらず

ここまで来てやっと「brew install 〜」ではなく「pip install 〜」を実行すべきだったと気づいて「pip install mysqlclient」を実行してみましたが、すでに完了しているとのことで何も変わりませんでした。

(venv) % pip install mysqlclient
Requirement already satisfied: mysqlclient in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (2.0.3)
(venv) %

【mac】Python 仮想環境に Django プロジェクトと Django アプリケーションを作成する

  1. Django プロジェクトの作成
  2. Django アプリケーションの作成
  3. アプリケーションをプロジェクトに登録
  4. 動作確認
  5. 管理ユーザーの作成

Django プロジェクトの作成

仮想環境に入った状態で下記を実行します。今回例として仮想環境内に「Django_Project」フォルダを作ったのでその中に「sample_django_project」という名前の Django プロジェクトを作成します。

(sample_venv) % cd Django_Project
(sample_venv) Django_Project % django-admin startproject sample_django_project

すると下記の様に「Django_Project」フォルダの配下に「sample_django_project」フォルダとファイルが一式作成されます。

Django アプリケーションの作成

上の画像「manage.py」がある階層へ移動します。

(sample_venv) % cd sample_django_project

そして下記を実行して「sample_django_app」という名前で Django アプリケーションを作成します。

(sample_venv) sample_django_project % python manage.py startapp sample_django_app

すると、「sample_django_project」というプロジェクトの配下に「sample_django_app」が作成されました。

アプリケーションをプロジェクトに登録

アプリケーションフォルダの apps.py を開くと下記の通り「SampleDjangoAppConfig」というクラスがあるので、これをプロジェクトの settings.py に登録します。

from django.apps import AppConfig


class SampleDjangoAppConfig(AppConfig):
    name = 'sample_django_app'

settings.py の INSTALLED_APPS のリストに下記の通り「アプリケーション名.apps.クラス名」の形で追記します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'sample_django_app.apps.SampleDjangoAppConfig'
]

これで Django プロジェクトと Django アプリケーションの作成は完了です。

動作確認

ターミナルでコマンド「python manage.py runserver」を実行し、動作確認をします。

% python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
April 23, 2021 - 21:27:24
Django version 3.2, using settings 'sample_django_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

特に問題がなければ上記の様なログが表示されるはずです。

そしてブラウザの URL バーに「http://127.0.0.1:8000/」と入力して下記の画面が表示されたら OK です。

管理ユーザーの作成

仮想環境内、「manage.py」のある階層でコマンド「python manage.py createsuperuser」を実行します。

% python manage.py createsuperuser

するとユーザー名、メールアドレスをパスワードを設定する様促されるので設定を行います。

Username : adminuser #任意のユーザー名
Email address: xxxxxxxx@gmail.com
Password: 
Password (again): 
Superuser created successfully.
% python manage.py runserver

ブラウザで「http://127.0.0.1:8000/admin/」にアクセスすると、管理ユーザーのログイン画面が表示されます。

ログインすると下記の通り管理ユーザー用画面が表示されます。

Mac で Python 仮想環境に Django をインストールしたい

Python の仮想環境を作る

仮想環境を作成したいディレクトリへ行き、下記のコマンドを実行します。例として「sample_virtual_environment」という仮想環境を作ります。

 python3 -m venv sample_virtual_environment

すると下記の様に Python の実行に必要なファイルやフォルダが一式作成されます。

これで仮想環境の作成は完了です。実際に仮想環境「sample_virtual_environment」を起動するには下記を実行します。

% cd sample_virtual_environment/bin
% source activate

下記の様にカッコの中に仮想環境の名前が表示されると思います。

(sample_virtual_environment) %

仮想環境から出たい場合は「deactivate」を実行します。

(sample_virtual_environment) % deactivate
%

Django をインストールする

仮想環境で Django をインストールするには、仮想環境を activate した状態で下記を実行します。

(sample_virtual_environment) % pip install django

下記のようなログが表示されて最後の方に「Successfully installed」と出ていれば成功です。

(sample_virtual_environment) % pip install django
Collecting django
  Downloading https://files.pythonhosted.org/packages/b8/6f/9a4415cc4fe9228e26ea53cf2005961799b2abb8da0411e519fdb74754fa/Django-3.1.7-py3-none-any.whl (7.8MB)
     |████████████████████████████████| 7.8MB 337kB/s 
Collecting asgiref<4,>=3.2.10 (from django)
  Downloading https://files.pythonhosted.org/packages/89/49/5531992efc62f9c6d08a7199dc31176c8c60f7b2548c6ef245f96f29d0d9/asgiref-3.3.1-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from django)
  Downloading https://files.pythonhosted.org/packages/14/05/6e8eb62ca685b10e34051a80d7ea94b7137369d8c0be5c3b9d9b6e3f5dae/sqlparse-0.4.1-py3-none-any.whl (42kB)
     |████████████████████████████████| 51kB 9.6MB/s 
Collecting pytz (from django)
  Downloading https://files.pythonhosted.org/packages/70/94/784178ca5dd892a98f113cdd923372024dc04b8d40abe77ca76b5fb90ca6/pytz-2021.1-py2.py3-none-any.whl (510kB)
     |████████████████████████████████| 512kB 8.1MB/s 
Installing collected packages: asgiref, sqlparse, pytz, django
Successfully installed asgiref-3.3.1 django-3.1.7 pytz-2021.1 sqlparse-0.4.1
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(sample_virtual_environment) %

以上で Django のインストールは完了です。続けて Django プロジェクトそして Django アプリケーションの作成はこちらの記事へ。

import MySQLdb で実際にクエリを実行できるか確認する

mysqlclient をインストールしたので、実際にクエリを実行できるか簡単に確認します。

今回は WordPress で自動作成されたテーブルで、現在公開されている記事のタイトルを select しました。

% python3
Python 3.9.0 (default, Jan  3 2021, 10:29:59) 
[GCC 4.2.1 20070831 patched [FreeBSD]] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.

>>> import MySQLdb
>>> conn = MySQLdb.connect(host='mysqlXXX.db.sakura.ne.jp', db='abcabc_notemite',user='abcabc',passwd='xxxxxxxxxxxx',charset='utf8mb4')
>>> c = conn.cursor()
>>> c.execute('select post_title from nm_posts where post_status = "publish"')
20
>>> c.fetchall()
(('サンプルページ',), ('【Wordpress】ショートコードを別ファイル管理でリスク低減',), ('【WordPress】ショートコードの表示・非表示を一発で切り替えたい',), ('【ターミナル】Mac のログインシェルを zsh に変える',), ('【Python】Macbook に Python3 をインストール',), ('【Python】「pip install requests」でエラー「pip3 install requests」で成功',), ('【Python】Mac に Beautifulsoup4 をインストール',), ('Homebrew を Macbook Pro へインストール',), ('Homebrew を使って Macbook に Wget をインストール',), ('【Wordpress】確かに「--」と書いたのに「–」と表示される件',), ('【8ステップでがんばる】さくらレンタルサーバーでWordPressサイト立ち上げ',), ('【ターミナル】さくらのレンタルサーバーにSSHでログインする方法',), ('さくらレンタルサーバに Python3 をインストールする方法',), ('【Python】さくらレンタルサーバーに requests モジュールをインストール',), ('【Python】Mac に MySQL モジュールをインストールする方法',), ('【2020年10月〜12月】YouTube 急上昇入りランキング',), ('さくらレンタルサーバーに libffi をインストールする',), ('【2020年1月〜】YouTube 急上昇入りランキング',), ('さくらレンタルサーバーで Python3 を再インストール',), ('【Python3】mysqlclient のために _ctypes と格闘した記録',))
>>> 

execute() の実行結果(上記「20」の部分)はクエリの結果として返されたレコード数を表示しています。fetchall() を実行しないとクエリの実行結果は見れないんですね。

さくらレンタルサーバーで Python3 を再インストール

一度 Python3 をインストールしたのですが、mysqlclient をインストールするために Python3 を入れ直す必要があったのでそのステップを書きます。

アンインストール(仮)

まずは既存の Python3 を一旦アンインストールします。インストール先のフォルダを削除する必要があると思いますが、削除は怖いので一旦フォルダ名だけ変えます。

下記の通りパスが通っている状態です。

% which python3
/home/abcabc/local/python/bin/python3
% which pip3
/home/abcabc/local/python/bin/pip3

フォルダ名が変わったため、パスが通っていない状態になりました。

% which python3
python3: Command not found.
% which pip3
pip3: Command not found.

ダウンロード〜インストール

ここから先は基本的に下記の記事でやった内容をなぞるだけですが、今回 ./configure 文を変えました。

ダウンロード

% mkdir -p ~/work/python3
% cd ~/work/python3
% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

解凍

% tar zxf Python-3.9.0.tgz

インストール

% cd ./Python-3.9.0
% ./configure --prefix=$HOME/local/python/ --with-system-ffi LDFLAGS="-L $HOME/local/lib/" CPPFLAGS="-I $HOME/local/include/"
%  make
%  make install

ここまで完了したら、以前通したパスが生きているので下記の通り which コマンドで既に確認できる状態です。

% which python3
/home/abcabc/local/python/bin/python3
% which pip3
/home/abcabc/local/python/bin/pip3

使い終わったフォルダとファイルの削除

最後にファイルダウンロード用に作ったフォルダと、既存の Python3 が入っていたフォルダ(の名前を変えたもの)を削除します。

% rm -r ~/work/python3
% rm -r ~/local/python_20210103

ついでに

環境変数の追加

初めて Python3 をインストールした時はスルーしていましたが、どうやら下記を .cshrc に追記した方が良いみたいなのでこのタイミングで追記しておきます。

setenv  PYTHON $HOME/local/python/lib
setenv  PYTHONPATH $HOME/local/python/lib/python3.9/site-packages

requests モジュールをインストール

元々インストールしてあった requests モジュールを再度インストールします。

% pip3 install requests

【Python3】mysqlclient のために _ctypes と格闘した記録

経緯

さくらのレンタルサーバー上で MySQL のデータベースを使えるので、それを Python で操作したいと思ったのが始まりです。mysqlclient を使えば良いらしかったので「pip3 install mysqlclient」を実行するも、エラーが出て成功しない。なんとかインストールを終えるまでの過程が文系の私には?だいぶややこしかったのでその記録を書き留めます。

  1. 問題発生1(No module named '_ctypes')
  2. 調査と原因1(libffi が無い)
  3. libffi をインストール(sudo は使えない)
  4. 問題発生2(INFO: Could not locate ffi libs and/or headers)
  5. 調査と原因2(./configure 文の修正)
  6. 解決(mysqlclient インストール成功)

問題発生1(No module named '_ctypes')

上記の通り「pip3 install mysqlclient」を実行したところ、下記のエラーが出てインストールが失敗しました。

ModuleNotFoundError: No module named '_ctypes'

直訳すると「_ctypes モジュールがありません」

_ctypes モジュールとはなんぞや。そしてそれはどこにあるのでしょうか。。。

調査と原因1(libffi が無い)

取り敢えず知識ゼロから出来ることは、情報の海に身を投げてなんとなくわかるまで溺れること。。。調べた結果断片的ですが自分の理解できる範囲で下記の情報が得られました。

  • _ctypes と libffi
    • _ctypes は C 言語で書かれたライブラリを Python から利用するためのモジュールであり、libffiに依存している。
    • ソースからPythonをビルドする際、libffiが見つからない場合は _ctypes のビルドはスキップされる。
    • _ctypes がビルドされていない Python から _ctypes を利用しようとすると、当該エラー(ModuleNotFoundError: No module named '_ctypes')が発生する。
  • 原因
    • つまり、libffi がインストールされていない状態で Python をインストールしたため、_ctypes のビルドがされていなかった。
  • 解決方法
    • 当該エラーを解消するには、libffi をインストールした上で Python を再ビルド・再インストールする必要がある。

libffi をインストール(sudo は使えない)

「sudo apt-get install -y libffi-dev」というコマンドが出てきましたが、さくらのレンタルサーバー(スタンダード)では管理者権限が与えられていないので sudo が使えません。

% sudo apt-get install -y libffi-dev
/usr/local/bin/sudo: Permission denied.

この通り、拒否されてしまいます。諸々調べた結果下記の方法でインストール出来ました。

問題発生2(INFO: Could not locate ffi libs and/or headers)

めでたく libffi をインストール出来たので Python をインストールし直しました。が、念のため make のログを確認したところ下記を発見。

INFO: Could not locate ffi libs and/or headers

Failed to build these modules:
_ctypes               _zoneinfo 

直訳すると「ffi libs およびヘッダーが見つからず _ctypes モジュールと _zoneinfo モジュールをビルド出来ませんでした。」とのこと。ショック。

しょうがないのでとりあえず続けて make install しましたが、当然 _ctypes モジュールが無いので「pip3 install mysqlclient」を実行しても前回と全く同じエラーで失敗します。

ModuleNotFoundError: No module named '_ctypes'

調査と原因2(./configure 文の修正)

また海に放り出されました。今回は「INFO: Could not locate ffi libs and/or headers」の文言を頼りに調べました。

こちらのページ(英語)を見たところ、どうやら CPPFLAGS、LDFLAGS、PKG_CONFIG_PATH の設定が必要みたいです。PKG_CONFIG_PATH の設定は libffi のインストールの時に行っていたので、取り敢えず CPPFLAGS と LGFLAGS だけでやってみます。

python-3.9.0.tgz は残して他を消し、再度下記の「./configure」文で Python のインストールを試してみます。

./configure --prefix=$HOME/local/python/ --with-system-ffi LDFLAGS="-L $HOME/local/lib/" CPPFLAGS="-I $HOME/local/include/"
項目雑なメモ
--prefixPython3 をインストールする場所
--with-system-ffilibffi のシステムバージョンへの接続を有効にするスイッチ。
CPPFLAGSCプリプロセッサのオプション
include パスを入れるっぽい?
LDFLAGSリンク用のディレクトリを指定する。
lib フォルダを入れるっぽい?

解決(mysqlclient インストール成功)

上記の「./configure」文のあとで make を実行しました。そしてログを確認すると下記の通り _ctypes のエラーはなくなりました。_zoneinfo は何かよくわかりませんし特に今回必要だとも思ってないので無視します。

Failed to build these modules:
_zoneinfo

今回は「pip3 install mysqlclient」も無事成功しました。

% pip3 install mysqlclient
Collecting mysqlclient
  Using cached mysqlclient-2.0.3.tar.gz (88 kB)
Using legacy 'setup.py install' for mysqlclient, since package 'wheel' is not installed.
Installing collected packages: mysqlclient
    Running setup.py install for mysqlclient ... done
Successfully installed mysqlclient-2.0.3
WARNING: You are using pip version 20.2.3; however, version 20.3.3 is available.
You should consider upgrading via the '/home/xxxxxx/local/python/bin/python3.9 -m pip install --upgrade pip' command.
% 

【Python】Mac に MySQL モジュールをインストールする方法

環境

OS: macOS Catalina バージョン 10.15.4
Python: Python 3.8.3

やりたいこと

Python で MySQLdb モジュールを使える様にしたい。

mysql をインストール

まず Homebrew で MySQL をインストールする必要があります。これをしていないとこの後 pip で「mysqlclient」のインストールができません。「brew install mysql」を実行します。

(scraping) % brew install mysql
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
acl2                       heksa                      nfpm
act                        httpx                      ngs
airshare                   hy                         notmuch-mutt
alsa-lib                   i686-elf-binutils          numcpp
amp                        i686-elf-gcc               oci-cli
apidoc                     idris2                     omake
arb                        infracost                  openfst
argo                       inja                       oq
argocd                     inko                       ormolu
arrayfire                  ioctl                      ory-hydra
asimov                     jerryscript                osi
asroute                    jimtcl                     osm
athenacli                  jinx                       packetbeat
austin                     jobber                     packr
awsweeper                  jsonnet-bundler            pandoc-include-code
blogc                      k9s                        pandocomatic
bombadillo                 kde-karchive               parallel-hashmap
bond                       kde-kdoctools              periscope
borgbackup                 kde-ki18n                  pipgrip
box2d                      kde-threadweaver           po4a
buildozer                  kona                       podman
c7n                        kondo                      postgresql@12
cadence                    ksync                      prometheus-cpp
carton                     kubie                      promtail
cassowary                  ladspa-sdk                 protoc-gen-go-grpc
castget                    latexindent                protoc-gen-gogo
cbc                        ldpl                       protoc-gen-gogofaster
cdktf                      leaf                       pwncat
cgl                        libaio                     python@3.7
chalk-cli                  libcouchbase@2             python@3.9
charge                     libdmx                     reg
chart-testing              libdrm                     rgf
choose-rust                libfontenc                 rqlite
chrony                     libfs                      rust-analyzer
clair                      libgccjit                  rustscan
clang-format@8             libgnt                     s2n
cli11                      libhandy                   saltwater
cloud-nuke                 libice                     scw@1
cloudformation-cli         libirecovery               sdns
cloudformation-guard       libmnl                     server-go
coconut                    libnetfilter-queue         shallow-backup
colfer                     libnetworkit               sheldon
commitizen                 libnfnetlink               shtools
copilot                    liboqs                     silicon
coredns                    libpciaccess               simdjson
cortex                     libpthread-stubs           skylighting
cpio                       libseccomp                 sleef
cpm                        libsm                      smlpkg
cpr                        libx11                     snap
croaring                   libxau                     so
croc                       libxaw                     solidity
cubejs-cli                 libxaw3d                   sonic
cvs-fast-export            libxcb                     sponge
datasette                  libxcomposite              sqlite-utils
dbdeployer                 libxcursor                 standardese
diskonaut                  libxdamage                 staticcheck
dnsprobe                   libxdmcp                   structurizr-cli
doctest                    libxext                    subfinder
dosbox-staging             libxfixes                  termcolor
dotnet                     libxfont                   terraform-ls
duckscript                 libxft                     terraform@0.12
eksctl                     libxi                      terrascan
eleventy                   libxinerama                tfsec
empty                      libxkbfile                 thanos
envoy                      libxmu                     toot
fava                       libxpm                     torchvision
fblog                      libxrandr                  tre-command
fennel                     libxrender                 trunk
fetch                      libxres                    ugrep
flank                      libxscrnsaver              uptoc
fleet-cli                  libxshmfence               usb.ids
flit                       libxt                      util-macros
folderify                  libxtst                    vapor
font-util                  libxv                      vcpkg
foreman                    libxvmc                    vgrep
fpart                      libxxf86dga                vivid
fpdns                      libxxf86vm                 vlang
functionalplus             litecli                    volk
gateway-go                 localstack                 vsearch
gcc@9                      logcli                     vtk@8.2
git-hooks-go               loki                       webify
git-hound                  lunchy                     wgcf
gitql                      lunchy-go                  wownero
gitui                      macos-trash                wren
gluon                      mandown                    wren-cli
go@1.14                    mariadb@10.4               x86_64-elf-gdb
gofish                     marked                     xcb-proto
golangci-lint              mask                       xdpyinfo
gostatic                   matplotplusplus            xorgproto
gradle-profiler            mhonarc                    xtrans
gravity                    microplane                 yj
grpcui                     naabu                      z.lua
gulp-cli                   nanorc                     zoxide
halide                     nest                       zsh-you-should-use
hashlink                   networkit
hasura-cli                 never
==> Updated Formulae
Updated 4645 formulae.
==> Renamed Formulae
elasticsearch@6.8 -> elasticsearch@6
gst-validate -> gst-devtools
interactive-rebase-tool -> git-interactive-rebase-tool
jfrog-cli-go -> jfrog-cli
kibana@6.8 -> kibana@6
mkl-dnn -> onednn
==> Deleted Formulae
baidupcs-go         elasticsearch@5.6   marathon-swift      unravel
biogeme             highlighting-kate   python              urbit
cargo-completion    i386-elf-grub       residualvm          wpscan
cryptopp            kibana@5.6          sflowtool           xu4
elasticsearch@2.4   lumo                tomee-jax-rs

==> Downloading https://homebrew.bintray.com/bottles/openssl%401.1-1.1.1h.catali
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/4e5357c0cfd55cfa4ef0b
######################################################################## 100.0%
==> Downloading https://homebrew.bintray.com/bottles/protobuf-3.13.0.catalina.bo
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/af2990ba0a6e5588ef2af
######################################################################## 100.0%
==> Downloading https://homebrew.bintray.com/bottles/mysql-8.0.21_1.catalina.bot
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/81e92d0df39edaff415e7
######################################################################## 100.0%
==> Installing dependencies for mysql: openssl@1.1 and protobuf
==> Installing mysql dependency: openssl@1.1
==> Pouring openssl@1.1-1.1.1h.catalina.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

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

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

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

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

==> Summary
🍺  /usr/local/Cellar/openssl@1.1/1.1.1h: 8,067 files, 18.5MB
==> Installing mysql dependency: protobuf
==> Pouring protobuf-3.13.0.catalina.bottle.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/protobuf
==> Summary
🍺  /usr/local/Cellar/protobuf/3.13.0: 266 files, 19.8MB
==> Installing mysql
==> Pouring mysql-8.0.21_1.catalina.bottle.tar.gz
==> /usr/local/Cellar/mysql/8.0.21_1/bin/mysqld --initialize-insecure --user=ken
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start
==> Summary
🍺  /usr/local/Cellar/mysql/8.0.21_1: 290 files, 291.2MB
==> `brew cleanup` has not been run in 30 days, running now...
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/gettext--0.20.2_1.catalina.bottle.tar.gz... (8.4MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/libidn2--2.3.0.catalina.bottle.tar.gz... (233.6KB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/libunistring--0.9.10.catalina.bottle.tar.gz... (1.4MB)
Removing: /usr/local/Cellar/openssl@1.1/1.1.1g... (8,059 files, 18MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/openssl@1.1--1.1.1g.catalina.bottle.tar.gz... (5.3MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/tree--1.8.0.catalina.bottle.tar.gz... (49.5KB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/wget--1.20.3_2.catalina.bottle.tar.gz... (1.4MB)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/tree... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/wget... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/libidn2... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/libunistring... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/gettext... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/openssl@1.1... (64B)
Pruned 1 symbolic links and 2 directories from /usr/local
==> Caveats
==> openssl@1.1
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

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

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

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

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

==> protobuf
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/protobuf
==> mysql
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start

長々とログが出ましたが、入力待ちになったら which コマンドで mysql がインストールされたのを確認します。

(scraping) % which mysql
/usr/local/bin/mysql

/usr/local/bin/mysql にインストールされています。

MySQL の動作を確認

MySQL を起動

「mysql.server start」と入力して MySQL を起動してみます。

% mysql.server start
Starting MySQL
.. SUCCESS! 
% 

無事起動しました。

MySQL をシャットダウン

「mysql.server stop」でシャットダウンすることができます。

% mysql.server stop
Shutting down MySQL
.. SUCCESS!
%

mysqlclient をインストール

pip で mysqlclient をインストールします。

(scraping) % pip install mysqlclient
Collecting mysqlclient
  Using cached https://files.pythonhosted.org/packages/a5/e1/e5f2b231c05dc51d9d87fa5066f90d1405345c54b14b0b11a1c859020f21/mysqlclient-2.0.1.tar.gz
Installing collected packages: mysqlclient
  Running setup.py install for mysqlclient ... done
Successfully installed mysqlclient-2.0.1
WARNING: You are using pip version 19.2.3, however version 20.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(scraping) % 

MySQLdb モジュールが使えることを確認

Python で MySQLdb モジュールがインポートできることを確認して完了です。

>>> import MySQLdb
>>> 

【Python】さくらレンタルサーバーに requests モジュールをインストール

いきなり request をインポートしようとすると「request モジュールがありません」とのことでエラーが出てしまいます。

>>> import requests
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'requests'

なので一旦 Python は exit() します。そして pip3 で request をインストール。

>>> exit()
% pip3 install requests

すると下記の様に諸々のダウンロードが実行され一瞬で入力待ち状態に戻ります。

% pip3 install requests
Collecting requests
  Downloading requests-2.24.0-py2.py3-none-any.whl (61 kB)
     |████████████████████████████████| 61 kB 692 kB/s 
Collecting certifi>=2017.4.17
  Downloading certifi-2020.6.20-py2.py3-none-any.whl (156 kB)
     |████████████████████████████████| 156 kB 6.7 MB/s 
Collecting idna<3,>=2.5
  Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
     |████████████████████████████████| 58 kB 7.5 MB/s 
Collecting chardet<4,>=3.0.2
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
     |████████████████████████████████| 133 kB 16.4 MB/s 
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
  Downloading urllib3-1.25.10-py2.py3-none-any.whl (127 kB)
     |████████████████████████████████| 127 kB 20.1 MB/s 
Installing collected packages: certifi, idna, chardet, urllib3, requests
Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.10
% 

入力待ちになったら Python3 を起動。

% python3

そしてそのまま request をインポートしてみます。

>>> import requests
>>>   

今回はエラーが出ず入力待ち状態になりました。試しにそのまま Yahoo! のソースコードを表示してみます。

>>> import requests
>>> r = requests.get('http://yahoo.com/')
>>> r.text
'<!DOCTYPE html>\n<html id="atomic" lang="en-US" class="atomic   l-out Pos-r https fp fp-v2 fp-default mini-uh-on uh-topbar-on ltr desktop Desktop bkt201">\n<head>\n    <meta http-equiv="X-UA-Compatible" content="IE=edge">\n    \n    <title>Yahoo</title><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="//s.yimg.com"><link rel="preconnect" href="//s.yimg.com">

問題なさそうですね。これで request のインストールは完了です。

さくらレンタルサーバに Python3 をインストールする方法

さくらレンタルサーバには Python2 系が入っているのですが、Python2 はもう推奨されていないので 3 系をインストールする方法を紹介します。ちなみに私は Mac ユーザーなのでターミナルを使用しています。

  1. ssh でさくらレンタルサーバにログイン
  2. ダウンロード用のフォルダを作成
  3. wget でファイルをダウンロード
  4. ファイルを解凍する
  5. インストール
  6. パスを通す
  7. 設定を反映
  8. パスが通ったことを確認して完了

ssh でさくらレンタルサーバにログイン

まずはターミナルを立ち上げ、ssh でさくらレンタルサーバにログインします。

Last login: Sun Oct 11 10:43:12 on ttys000
% ssh XXXXXX@XXXXXX.sakura.ne.jp
XXXXXX@XXXXXX.sakura.ne.jp's password: 

ダウンロード用のフォルダを作成

ファイルをダウンロードする前に、ダウンロード用のフォルダを作っておきます。下記のコマンドで「work」フォルダとその配下に「python3」フォルダを作成します。

% mkdir -p ~/work/python3

FTPクライアントで見てみると下記の様に各フォルダが作成されているのが確認できます。

wget でファイルをダウンロード

% cd ~/work/python3
% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

ファイルがダウンロードされ、下記の様に入力待ちになれば無事ダウンロード完了です。

% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
--2020-10-11 12:39:03--  https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
Resolving www.python.org... 151.101.88.223, 2a04:4e42:15::223
Connecting to www.python.org|151.101.88.223|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 26724009 (25M) [application/octet-stream]
Saving to: 'Python-3.9.0.tgz'

Python-3.9.0.tgz    100%[=====================>]  25.49M  43.9MB/s   in 0.6s   

2020-10-11 12:39:03 (43.9 MB/s) - 'Python-3.9.0.tgz' saved [26724009/26724009]

% 

念のため覗いてみると、先ほど作成した「python3」フォルダのなかに「Python-3.9.0.tgz」のファイルがダウンロードされているのが分かります。

ファイルを解凍する

% tar zxf Python-3.9.0.tgz

ファイルが解凍され、元々ダウンロードした圧縮ファイルとは別に「Python-3.9.0」という名前のフォルダが作成されています。

インストール

解凍されたフォルダ「Python-3.9.0」に移動します。

% cd ./Python-3.9.0

次に ./configure を実行しますが、その際 prefix を使ってインストールするディレクトリを指定します。

% ./configure --prefix=$HOME/local/python/

実行するとプロセスが走ってドバドバとターミナルに表示されますが、下記が表示されて入力待ちの状態になったら完了です。

creating Modules/Setup.local
creating Makefile

「make」を実行します。

%  make

しばらくプロセスが走るので入力待ちになるまで待ちます。次に「make install」を実行します。

%  make install

またプロセスが走るので最後下記の様な表示が出て入力待ちになるまで待ちます。

Installing collected packages: setuptools, pip
  WARNING: The script easy_install-3.9 is installed in '/home/XXXXXX/local/python/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts pip3 and pip3.9 are installed in '/home/XXXXXX/local/python/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-20.2.3 setuptools-49.2.1
% 

実は上のログに2箇所「WARNING」として警告が表示されているのですが、その内容が以下の通り。

WARNING:スクリプトeasy_install-3.9は、「PATH」にない「/home/XXXXXX/local/python/bin」にインストールされています。このディレクトリを「PATH」に追加することを検討してください。
WARNING:スクリプトpip3およびpip3.9は、「PATH」にない「/home/XXXXXX/local/python/bin」にインストールされています。このディレクトリを「PATH」に追加することを検討してください。

これは後ほど .cshrc ファイルを編集して解決します。

local > python というディレクトリが作られ、さらにその配下に様々なフォルダが作られています。

パスを通す

python3 と pip3 のインストール自体は完了しましたが、この状態だとまだ python3 や pip3 と言ったコマンドを直接使うことができません。いわゆる「パスが通っていない」状態です。「which」コマンドを実行しても下記の通りエラーが返ってきます。

% which python3
python3: Command not found.
% which pip3
pip3: Command not found.

python3 と pip3 が両方とも「$HOME/local/python/bin」にインストールされている状態です。

.cshrc ファイルを編集することでパスを通しますが、この作業をする前に必ず .cshrc のバックアップをとっておきましょう。

% cd ~/
% vi .cshrc

.cshrc の内容がターミナルに表示されます。

# $FreeBSD: src/share/skel/dot.cshrc,v 1.14.6.1 2008/11/25 02:59:29 kensmith Exp
 $
#
# .cshrc - csh resource script, read at beginning of execution by each shell
#
# see also csh(1), environ(7).
#

alias h         history 25
alias j         jobs -l
alias la        ls -a
alias lf        ls -FA
alias ll        ls -lA

# A righteous umask
umask 22

set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin)

setenv  EDITOR  vi
setenv  PAGER   more
setenv  BLOCKSIZE       K
setenv  PKG_DBDIR       ~/db/pkg

if ($?prompt) then
        # An interactive shell -- set some stuff up
        set filec
        set history = 100
        set savehist = 100
        set mail = (/var/mail/$USER)
        if ( $?tcsh ) then
                bindkey "^W" backward-delete-word
                bindkey -k up history-search-backward
                bindkey -k down history-search-forward
        endif
endif

このファイルの最後に「set path = ($path $HOME/local/python/bin)」を追記したいのですが、手順が少しややこしいので下記の記事などを参考にしつつ行ってください。

以下の様に、ファイルの一番最後に一行だけ追記しました。

                bindkey "^W" backward-delete-word
                bindkey -k up history-search-backward
                bindkey -k down history-search-forward
        endif
endif
set path = ($path $HOME/local/python/bin)

設定を反映

.cshrc で変更した内容を反映させます。

% source ~/.cshrc
% rehash

パスが通ったことを確認して完了

パスを通す前はエラーが返ってきた「which」コマンドですが、今回はきちんと python3、pip3 のパスが表示されます。

% which python3
/home/XXXXXX/local/python/bin/python3
% which pip3
/home/XXXXXX/local/python/bin/pip3
% 

バージョン情報もきちんと表示されます。

% python3 --version
Python 3.9.0
% pip3 --version
pip 20.2.3 from /home/XXXXXX/local/python/lib/python3.9/site-packages/pip (python 3.9)
% 

最後に圧縮ファイルのダウンロードに使ったフォルダとファイルを削除して完了です。

% rm -r ~/work/python3