stylesheet

ラベル programming の投稿を表示しています。 すべての投稿を表示
ラベル programming の投稿を表示しています。 すべての投稿を表示

2024-08-17

Flaskアプリケーションをサブディレクトリで公開

Flaskで作成したアプリケーションをサブディレクトリにマウントして公開する方法。 Flaskの機能ではないのでドキュメントを見ていてもなかなか見つけにくいが、WSGIミドルウェアを使用するものが正解。

毎回調べている気がするのでメモしておく。

設定内容

以下のように、http://localhost/consoleで公開する。

# nginx config

upstream console {
  server 127.0.0.1:8110;
}

server {
  ...

  location /console {
    proxy_pass http://console;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  ...
}

このままではurl_for等のurl生成が壊れるので、 APPLICATION_ROOTを設定してやり、WSGIのミドルウェアを挟んでやるとうまく動作する。 環境変数を参照するようにすると、開発環境等にもコード修正なしで対応できる。

# app.py

import os
from flask import Flask, request, url_for, render_template
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher import DispatcherMiddleware

application = Flask(__name__)

application_root = os.environ.get('FLASK_APPLICATION_ROOT', '')
application.config['APPLICATION_ROOT'] = application_root

application.wsgi_app = DispatcherMiddleware(run_simple, {application_root: application.wsgi_app})


@application.route('/')
def index():
    urls = (
        url_for('index', _external=True),
        url_for('index'),
        url_for('static', filename='css/style.css'))
    return '<br>'.join(urls)


if __name__ == "__main__":
    application.run(host=0.0.0.0)

今回は、WSGIコンテナにNGINX Unitを使用してみた。 インストール方法は割愛。

# config.json

{
    "listeners": {
        "*:8110": {
            "pass": "applications/console"
        }
    },
    "applications": {
        "console": {
            "type": "python",
            "user": "yamori",
            "group": "yamori",
            "working_directory": "/home/yamori/workspace/console/",
            "path": "/home/yamori/workspace/console/",
            "home": "/home/yamori/.anyenv/envs/pyenv/versions/console",
            "module": "app",
            "environment": {
                "FLASK_APPLICATION_ROOT": "/console"
            }
        }
    }
}

ソケットにputして反映させる。

$ sudo curl -X PUT --data-binary @config.json --unix-socket /run/control.unit.sock http://localhost/config/

以上で、webサーバー経由でのアクセスhttp://localhost/console、pythonファイルの直接実行時のhttp://localhost:5000どちらの場合でも正しいパスが生成される。

2023-05-28

diffusers の使い方を調べてGoogle Colab ノートブックファイルを作った

概要: この記事では、Google Colabのフリー版におけるAUTOMATIC1111版WebUIの制限について取り上げ、その代替手段としてHugging Faceのdiffusersを使用する方法について調査します。

最近、Google Colabのフリー版での利用制限が行われ、AUTOMATIC1111版WebUIの使用が禁止されました。さらに悪いことに、この制限はRemoteUI全体に広がっているようです。
この制限によって、以前は簡単にアクセスできていたWebユーザーインターフェース(WebUI)を使用することができなくなりました。AUTOMATIC1111版WebUIは、使いやすく便利なユーザーインターフェースでしたが、これからは別の方法を探さなければなりませんでした。

代替の手段を模索する必要がありました。
その結果、UIを持たないHugging Faceのdiffusersを利用することに決めました。diffusersは、モデルの推論や処理を行うためのPythonライブラリであり、UIを必要としないため、制限を受けずに利用することができます。これは私たちのニーズに合致していると考え、積極的に取り入れることにしました。

diffusersの使い方について詳しく調査しました。Hugging Faceの公式ドキュメンテーションやコミュニティのフォーラムなど、さまざまな情報源を活用しました。

2023-04-12

プログラマーには ChatGPT が必要だ

ChatGPT捗る。
これだけできると、非公開のプログラムコードも喰わせたくなる。
禁止されるのもわからないでもないな。

コードレビューの依頼

N.Y.

コードレビューをお願い

ChatGPT

もちろんです!コードを共有していただければ、レビューさせていただきます。

N.Y.
"""
マルチディスプレイ用の画像分割

python image_spliter.py -h

[requirements]
pillow
"""

import os
import glob
import argparse
import re
import logging
from PIL import Image, ImageFilter

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


def split_image(name:str, output:str, split:int, aspect:str):
    img = Image.open(name)
    ax, ay = map(lambda x: int(x), aspect.split(':'))
    aspect_ratio  = ay / ax

    out_w = int(img.width / split)
    out_h = int(out_w * aspect_ratio)
    if out_h > img.height:
        out_w = int(out_h * aspect_ratio)
    
    x = int(img.width / 2 - out_w * split / 2)
    y = int(img.height / 2 - out_h / 2)
    folder, file_name = os.path.split(name)
    base_name, ext = os.path.splitext(file_name)

    logger.info(f'processing... {name}, {img.width}x{img.height} -> {out_w}x{out_h}')

    for n in range(split):
        p = os.path.join(output, f'{base_name}_{n}{ext}')
        cropped = img.crop((x, y, x + out_w, y + out_h))
        cropped.save(p, quality=95)
        logger.info(f'cropped: {p}')
        x += out_w


def aspect_type(value:str) -> str:
    if not re.match(r'^\d+:\d+$', value):
        raise argparse.ArgumentError('invalid value')
    return value


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='マルチディスプレイ用の画像分割')
    parser.add_argument('input', help='入力ファイル globパターン')
    parser.add_argument('-o', '--output', default='output', help='出力ディレクトリ')
    parser.add_argument('-s', '--split', type=int, default=2, help='分割数')
    parser.add_argument('-a', '--aspect', default='16:9', help='ディスプレイの縦横比', type=aspect_type)
    args = parser.parse_args()

    os.makedirs(args.output, exist_ok=True)
    for s in glob.glob(args.input):
        split_image(s, args.output, args.split, args.aspect)

    logger.info('done')

ChatGPT

このコードは、指定された入力画像を複数の画像に分割し、それらを出力する Python スクリプトのようです。以下は、いくつかのコメントです。

  • コード全体の構造は良く整理されており、コードが読みやすくなっています。
  • それぞれの機能は、独自の関数に分割されており、単一の機能にフォーカスされています。
  • パラメータの解析には、Python の標準ライブラリである argparse が使用されています。
  • コマンドラインオプションのヘルプは、"-h" オプションで表示されます。
  • エラーの検査には、正規表現が使用されています。

最後に、いくつかの改善の提案です。

2022-09-18

Python SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED エラーの回避策

URLError: <urlopen error [SSL:
UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation
disabled (_ssl.c:1131)>

上記は、セキュリティリスクのあるhttpsアドレスを開いたときに発生するエラーとなる。
SSLプロトコルの不具合で、中間者攻撃に使用される脆弱性のためopenssl側で無効化されている。OpenSSL 3.0.0からデフォルトで無効化された。

本来はサーバー側をアップデートするのが筋だが、なかなかそういうわけにもいかないことも多い。リスクを承知で、クライアント側の無効状態を解除する方法をメモ。

環境は以下の通り。

$ python -c 'import ssl; print(ssl.OPENSSL_VERSION)'
OpenSSL 3.0.2 15 Mar 2022

$ python --version
Python 3.8.10

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
Codename:       jammy

回避策A: opensslの設定変更

opensslの設定を変更する方法。 /etc/ssl/openssl.confを編集して、system_default_sectセクションにOptions = UnsafeLegacyRenegotiation設定を追加する。

# /etc/ssl/openssl.conf

...
[ssl_sect]
system_default = system_default_sect

[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=2
Options = UnsafeLegacyRenegotiation

ただし、/etc/ssl/openssl.confを直接編集すると、システム全体に適用されてしまうので流石にそれはまずい。
実際は別の設定ファイルを用意して、環境変数でpythonプログラムへ渡してやると良い。

$ cp /etc/ssl/openssl.conf openssl_unsecure.conf
$ echo -e "Options = UnsafeLegacyRenegotiation\n" >> openssl_unsecure.conf
$ OPENSSL_CONF=/path/to/openssl_unsecure.conf python cherry.py

回避策B: プログラム改修

sslのオプションに0x4フラグを追加してやると回避できる。
開発版ではssl.OP_LEGACY_SERVER_CONNECT定数が追加されているが、現行バージョン3.10でも使用できないので直接、値を指定する。

import urllib.request
import ssl

ctx = ssl.create_default_context()
ctx.options |= 0x4  # ssl.OP_LEGACY_SERVER_CONNECT
resposne = urllib.request.urlopen('https://...', context=ctx)
...

build_openerを使う場合は、HTTPSHandlerを作成してやる。

opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=ctx))
...

開発版でのOP_LEGACY_SERVER_CONNECTについての記載。

.. data:: OP_LEGACY_SERVER_CONNECT

   Allow legacy insecure renegotiation between OpenSSL and unpatched servers
   only.

   This option is only available with OpenSSL 0.9.8m and later, and is disabled
   in default context since OpenSSL 3.0.0.

   .. versionadded:: 3.11

以上。
古いpython2向けのスクリプトをpython3向けへ移植している時に発生した。

参照

2022-08-03

flutter_web を netlify + github で CI/DI

flutter webで作成したお試しアプリをnetlifyで動かしてみたので、CI/DI (Continuous integration/Continuous Delivery) 設定手順をメモ。
注意すべきは、初期状態でflutterコマンドが使えないのでビルドでひと手間加える必要があること、GitHubのアクセス設定が見つけにくいこと、以上の2点。

設定手順

レポジトリの準備

レポジトリを作成し、netlify.tomlとbuild.shを追加してpushしておく。netlify側のデプロイ設定をnetlify.tomlに記載する。

https://docs.netlify.com/configure-builds/file-based-configuration/
# netlify.toml

[build]
command = "chmod 777 ./build.sh && ./build.sh"
publish = "build/web"

netlify.tomlでは、自前のシェルスクリプトを呼び出すよう指示。

# build.sh

FLUTTER=`which flutter`
if [ -z $FLUTTER ]; then
  if cd flutter 2>/dev/null; then
    git pull
    cd ..
  else
    git clone https://github.com/flutter/flutter.git -b stable --depth=1
  fi
  FLUTTER="flutter/bin/flutter"
fi

$FLUTTER config --enable-web
$FLUTTER pub get
$FLUTTER gen-l10n
$FLUTTER pub run flutter_native_splash:create
$FLUTTER pub run grinder download-data
$FLUTTER build web --release

flutterコマンドをインストールしてflutter buildを行う。
言語リソースの作成や、スプラッシュ画面の作成、gridnerタスク等も追加で実行。

接続とアクセス許可

Site SettingsのBuild & DeployでLink repository。
GitHubを選んで認証を行う。

一覧から対象のレポジトリを選ぶ。レポジトリが表示されていない場合はGitHub側でアクセス設定が必要。
[Configure the Netlify app on Github]リンクからGitHubの設定ページへ。(GitHub内ではSettings > Integrations: Applications > Installed Github Apps > Netlify: Configureとたどる)

Repository accessへリポジトリを追加してやる。

CI設定

netlify.tomlの内容で自動構成されるので、そのままデプロイできる。

以上で、設定完了。
レポジトリへPUSHするたびに自動でデプロイされる。

その他

デプロイのスキップ

デプロイをスキップしたい更新は、最終コミットのメッセージに[skip ci]や[skip netlify]と書いておくとスキップできるようだ。

https://docs.netlify.com/site-deploys/manage-deploys/#skip-a-deploy

ビルド作成API

また、任意のタイミングでデプロイさせたい場合は、APIが簡便に使える。sites/{SITE_ID}/buildsエンドポイントへPOSTするだけで良い。
SITE_ID、TOKEN共にnetlifyで作成・確認できる。

curl -XPOST -H "Authorization: Bearer {TOKEN}" https://api.netlify.com/api/v1/sites/{SITE_ID}/builds

使用したアプリ

コロナ感染症データを読み込むようにしたflutterサンプルコードの改修品を使用した。 実用性はほぼないが、過去に大騒ぎしていた頃のさざ波感は味わえる。

2020-09-23

AutoHotKeyで変換/無変換キーを有効利用

中古で安く手に入れたThinkpadの一体型パコパコパッドが、アレなもんで...。余ってる変換/無変換キーを活用するAutoHotKeyスクリプトを書いてみた。
このスクリプトを起動しておくと、変換/無変換キー/かなキーでそれぞれ右/左/中クリックを行うことができる。
また、同じキーで日本語入力のON/OFFを行うモードもつけているので、そちらの気がある方も便利に使えるのではと思う。

だだし、このスクリプトはUSキーマップ環境で日本語キーボードを使っている変態さん向けのプログラムだ。
完全な日本語環境では、いろいろとキーバインドが衝突して、動作に支障をきたす可能性があるので注意されたし。

2018-02-20

ansibleのインストール

PC初期化の毎に調べてる気がするので、ansibleのインストール方法をメモしておく。
OSはUbuntuを使用。

2018-01-14

Hなこと始めました

すぐに仕事で使えそうなKotlin、熟練者から最強との呼び名が高いRust。 どちらにしようか迷ってたはずなのに、なぜか、2018年度のお勉強はHaskellに決まりました。

関数型言語はEmacsの設定ファイルをコピペ位しかしたことがないド素人です。

2017-10-30

TensorFlow CPU最適化ビルド

PyPIからインストールしたCPU版のTensorFlowを使用していると以下のような警告が「毎回」出る。

W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.

訳すと「拡張命令に対応してるのに拡張命令サポートを有効にしてコンパイルされてないぜ。Why?」、意図するところは「tensorflowの実力はこんなものじゃないぜ。早くおまえのマシンとシンクロするんだ。」ということか。競合と速度比較されるので開発者も大変なのだろう。

ただの警告なので放置しても問題無いわけだが、使用するたびにログ出力されては気分がよろしくないのは確かではある。 それならばと、CPU最適化版へ取り替えようと思うわけだが、残念なことにPyPIではCPU最適化版の配布は行われていなかった。
この際であるから、手間はかかるとはいえ、いっそソースコードからビルドを試みてシンクロ率100%を目指すこととした。

2017-10-27

ECMAScript async/await 構文で記述する非同期処理

今年も終わりが見えてきた2017年の秋、最近はpromise.thenも過去のものになりつつあるようで。
今後は、async/awaitを使えるようになっておかないと、産廃扱いされそうなのでちょっと試してみます。

2017-10-12

mitmproxyでandroidの通信を改竄

mitmproxyはhttpsに対応したman-in-the-middle型のプロキシサーバー。
PC側でmitmproxyを起動してAndroid実機へプロキシ設定するだけでお手軽に通信を覗いたり改竄することができる。 Android端末にrootも不要なので、テストがとても捗る。

これでハイスコア更新したりありえない場所にワープしたりするのが流行ったとかなんとか。

2017-05-20

gitで履歴のCommitterとAuthorを一括変更

複数アカウントでいろんなプロジェクトを梯子してると、ずっと他プロジェクト用の名前でコミットしてしまっていたり...。よくあるのでメモ。

2013-10-01

IABv3: sharedUserIdを使用しているとエラー

sharedUserIdを使用しているアプリでin-app billing v3を使用すると例外が発生。

同じsharedUserIdを設定したアプリAとB

アプリAのみインストールした場合: 動作OK
アプリAとBをインストールした場合: InAppBillingServiceがエラーを返す

W/Finsky(20189): [27] InAppBillingService.validatePackageName: Package name ***.****.****** does not match the Uid
E/AS(27058): Problem setting up In-app Billing: IabResult: Error checking for billing v3 support. (response: 5:Developer Error)

不具合として承認されているが、半年ほど進展なし。

https://code.google.com/p/marketbilling/issues/detail?id=90

回避策

  • IABv2を使用するよう書き換える。
  • sharedUserIdを使用しない。

お。

追記

IABv2のサポート終了。この不具合は修正されているようです。

Beginning January 2015, we will end support for the In-app Billing Version 2 API. After this date, users will no longer be able to make in-app purchases using your app until you upgrade your app to use the Version 3 API.

2013-09-21

Androidナビゲーションバーにオーバーフローボタンを無理やり表示

レガシーアプリ互換性のためのアレ。targetSdkVersionをあげると表示されなくなるので、無理やり表示させてみる。
Androidアプリ開発ではよく使う?リフレクションを使用。setContentViewしてからWindowに隠しフラグをセットする。


public class HogeActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        setLegacyOverflow(getWindow(), true);
    }


    void setLegacyOverflow(Window window, boolean enable) {
        try {
            int flag = WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null);
            if (enable) {
                window.addFlags(i);
            } else {
                window.clearFlags(i);
            }

        } catch (NoSuchFieldException e) {
            // 2.3以下はフラグなし

        } catch (IllegalAccessException e) {
            // 使えなくなった...
        }
    }
}

参考:

http://android-developers.blogspot.jp/2012/01/say-goodbye-to-menu-button.html

2012-09-26

Linux版 の IntelliJ 11 のフォント汚いっす

DebianだとIntelliJ IDEA 11のGUIフォントにアンチエイリアスがかからずギザギザ。
それらしき設定もない(エディタ部の設定は有る)ので、JavaVMの起動オプションでなんとかするのが正解のよう。

JavaVMのアンチエイリアスを有効にするオプションを、bin/idea.vmoptions (bin/idea64.vmoptions) に追記。

-Dawt.useSystemAAFontSettings=on

IntelliJを再起動するとアンチエイリアスがかかったボケたフォントに変わる。

その他カラーテーマとか

http://ethanschoonover.com/solarized http://d.hatena.ne.jp/inouetakuya/20120122/1327233747

eclipseとかもうイラネ。emacsとintellijでおk。

2012-07-14

nodejsとnpmでインストールしたモジュール更新

socket.ioな自作サーバーモニタがchromeで動かなくなっていたので、環境を刷新。 たぶん古いsocket.io使ってるから。

2011-03-14

Windows7 x64でdulwich-0.7.0のビルドが通らなかった

mercurialでgitレポジトリをcloneできるようにするhg-gitプラグインをインストールしたときのメモ。

$ easy_install hg-git

Windows7 x64 + VC2008 + python2.7環境でeasy_installすると依存ライブラリdulwichのビルドで...

running build
running build_py
running build_ext
building 'dulwich._diff_tree' extension
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -Idulwich -IC:\usr\local\python2\include -IC:\usr\local\python2\PC /Tcdulwich/_diff_tree.c /Fobuild\temp.win-amd64-2.7\Release\dulwich/_diff_tree.obj
_diff_tree.c
dulwich/_diff_tree.c(267) : error C2065: 'mode_t' : 定義されていない識別子です。
dulwich/_diff_tree.c(267) : error C2146: 構文エラー : ')' が、識別子 'lmode' の前に必要です。
error: command '"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\cl.exe"' failed with exit status 2

こけました...

2011-03-09

pythonでgoogleにログインする

insightとかinsightとかapiが公開されていないGoogleサービスにpythonでログインする方法をメモ。
その他のサービスは素直に gdata-python-client を使ったほうがイイ。

手順は以下の通り

2010-08-28

Apache Solr + MySQL + PHP で全文検索のメモ

Apache Solr + MySQL + PHP で全文検索を行う時のメモ。

Apache Solr 1.4.1 (jetty)
MySQL 5.0 (mysql-connector-java-5.1.13)
PHP5