くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Amazon Linux2+Apache+virtualenv+python3+Djangoでアプリをデプロイ

Amazon Linux2がリリース版になってから、Djangoアプリをデプロイしたので、
その時の備忘録φ(..)メモメモ

特に、python3のインストールがつらかった。。

各種バージョンは以下の感じ

$ cat /etc/system-release
Amazon Linux 2

$ httpd -v
Server version: Apache/2.4.33 ()
Server built:   Jun 15 2018 20:38:53

$ python3 -V
Python 3.7.0rc1
$ pip3 -V
pip 9.0.3 from /usr/lib/python3.7/site-packages (python 3.7)

インストール

## enable python3 for Amazon Linux2
$ sudo amazon-linux-extras enable python3

## instal httpd and python3
$ sudo yum install -y httpd-devel python3-devel gcc gcc-c++

aws-extrasリポジトリに、python3.6.2があるが、python3-develがない。。
やむなくaws-coreのpython3.7.0.rc1のpython3-develをインストール。。

仮想環境(Virtualenv)の作成

### setup virtual env
$ cd /var/www/cgi-bin/sample_app/
$ sudo pip3 install virtualenv
$ virtualenv -p python3.7 virtualenv     # create virtual env
$ . virtualenv/sampleApp/bin/activate # activate

### setup libraries
$ pip3 install -r require/require.txt

Djangowsgi.pyの設定

それぞれのパスは以下の感じ。

  • Django Projectのパス:/var/www/cgi-bin/sample_app/
  • virtualenvのパス: /var/www/cgi-bin/sample_app/virtualenv/
  • Django Projectのwsgi.pyのパス:/var/www/cgi-bin/sample_app/wsgi.py
  • Django Projectのstaticディレクトリのパス:/var/www/cgi-bin/sample_app/sample_app/static/

各種パスに応じて、wsgi.pyを変更する

変更前
import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_app.settings")
application = get_wsgi_application()
変更後
import os
import site
import sys

# ----------------------------------
# django projectのパス
PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

# virtualenvのパッケージパス
site.addsitedir(os.path.join(PROJECT_ROOT, 'virtualenv', 'lib', 'python3.7', 'site-packages'))
# django projectのパス
site.addsitedir(os.path.join(PROJECT_ROOT))
# ----------------------------------

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_app.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Apache(conf)

Apacheの設定として、Django用のconfファイルを作成する。 * /etc/httpd/conf.d/wsgi_django.conf

※ いろいろやったけどうまくいかないので、python自体とpip mod_wsgiは全体共通に。。

# install mod_wsgi using pip
$ sudo pip3 install mod_wsgi

# find mod_wsgi.so
$ find /usr/local/lib64/python3.7 -type f -name "mod_wsgi*.so"
 # => /usr/local/lib64/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so

# create
$ sudo vim /etc/httpd/conf.d/wsgi_django.conf
# describe found .so path
LoadModule wsgi_module /usr/local/lib64/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so

Alias /static /var/www/cgi-bin/sample_app/sample_app/static
<Directory /var/www/cgi-bin/sample_app/sample_app/static>
  Require all granted
</Directory>

WSGIScriptAlias / /var/www/cgi-bin/sample_app/sample_app/wsgi.py
<Directory /var/www/cgi-bin/cryptocurrency_web>
  Require all granted
</Directory>
# apache を再起動
$ sudo systemctl restart httpd

参考にしたサイト様

【小ネタ】Pythonでいい感じに固定小数点を表示する

formatの仕方はいろいろあるが、いい感じには表示してくれない...

  • "g".format(...)」だと、指数表示なってしまう
  • "f".format(...)」だと、有効桁まで0埋めされてしまう

固定小数表記で、無駄な0は表示してほしくない場合のフォーマットはないので、
rstripなどを駆使するしかないっぽい

# floatを固定小数表記でいい感じに表示する
def format_float(value):
  return "{:,.f}".format(value).rstrip('0').rstrip('.')

print(format_float(3.0))
# => 3

print(format_float(0.000003))
# => 0.000003
# 四捨五入
def format_float_int(value):
  return "{:,}".format(round(value))

参考にしたサイト様

Pythonで並列処理(Joblib)

Pythonで並列/並行処理するのは、Joblibがよいらしいので、使ってみた。ときの備忘録φ(..)メモメモ

インストール
$ pip install joblib
使い方
from joblib import Parallel, delayed

def do_execute(param):
    # 関数の処理
    
if __name__ == "__main__":
    # マルチプロセス
    result = Parallel(n_jobs=-1)(delayed(do_execute)(param) for param in [1, 2, 3])
    
    # マルチスレッド
    result = Parallel(n_jobs=-1, backend="threading")(delayed(do_execute)(param) for param in [1, 2, 3])

参考にしたサイト様

【Android】Tablayoutでタブの幅を広げたり、タブの文字サイズを変えたい

小ネタ。Tablayoutは便利。

タブレットでもタブの幅を広げる

Material Design的には、タブレットでタブが2個のときは、 タブのサイズを小さくするらしい。。

<android.support.design.widget.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabGravity="fill"
            app:tabMode="fixed" />

app:tabMaxWidth="0dp"が重要らしい

タブの文字サイズを変える

styleを作って、TextAppearanceを設定する感じらしい

<style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">?android:textColorSecondary</item>
    <item name="textAllCaps">true</item>
</style>

参考にしたサイト様

【Android】 特定のViewのスクリーンショットを共有する

SNSなどへのシェア機能などで、画面のスクリーンショットを共有したかった。
Viewごとでキャプチャできるようなので、その時の備忘録φ(..)メモメモ

View view = ...; // スクリーンショットを取りたいView

// Viewのスクリーンショットを取得
File file = new File(dir, "tmp_image.png");
try (FileOutputStream fos = new FileOutputStream(file, false)) {
    view.setDrawingCacheEnabled(true);      // キャッシュを取得する設定にする
    view.destroyDrawingCache();                  // 既存のキャッシュをクリアする
    Bitmap capture = view.getDrawingCache();

    // 画像のフォーマットと画質と出力先を指定して保存
    capture.compress(Bitmap.CompressFormat.PNG, 100, fos);
    fos.flush();

    view.setDrawingCacheEnabled(false);
} catch (Exception e) {
    file = null;
}

// 共有する処理
ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(activity);
builder.setText("共有するメッセージ");
if (file != null) { // 画像がある場合
    builder.setType("image/png");
    builder.addStream(Uri.fromFile(file));
} else { // 画像がない場合
    builder.setType("text/plain");
}

builder.startChooser();

参考にしたサイト様

【Android】外部URLから画像を直接共有する

Picassoで読み込んでキャッシュをShareCompatで共有するのがよさそう

public void shareImage(String url, final AppCompatActivity activity) {
    Picasso.get().load(url).into(new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            Uri bmpUri = getLocalBitmapUri(bitmap, activity);
            if (bmpUri != null) {
                ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(activity);
                builder.setStream(bmpUri);
                builder.setType("image/*");
                builder.startChooser();
            }
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) { }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) { }
    });
}

参考にしたサイト様

【Android】targetSDK27でwindowIsTranslucent=trueを使うとAndroid8.0でCrashする

タイトル通り。。かなり、はまったので、備忘録φ(..)

  • targetSDK=27で<item name="android:windowIsTranslucent">true</item>を使うと、Android8.0でCrashする
  • Androidのバグらしい。targetSDKを26に下げると問題なく動作する
  • Android8.1では修正されているらしい

まさか、SDK側の問題とは。。いろいろ変えてもそれはだめだ。。

参考にしたサイト様