忍者ブログ
Admin / Write / Res
ちゃんとカテゴリ分けされておりませんので、 記事をお探しならブログ内検索が便利です。 ご活用くださいませー+.(≧∀≦)゚+.゚
ブログ内検索
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
カウンター
アクセスカウンター
最新コメント
[04/05 Fully Vaccinated Adorable Escort Service in bengaluru 8273600238]
[03/26 Tonaldcet]
[01/16 jilibet]
[10/20 Call Girl in Delhi]
[09/07 לפרטים נוספים]
最新トラックバック
プロフィール
+ハンドル+
y_ayamori(purple)
+職業+
IT系エンジニア
+すまい+
さいたま
バーコード
[1]  [2]  [3]  [4]  [5]  [6]  [7

サクッとDjangoを動かしてみるの続きです。

とりあえず動的なページはさておき(とはいえ動的なページ主役ですが)が、静的なページにアクセスできるようにしてみましょう。
CSSやJS、画像など以外にも静的なページも重要です。

とはいえ、諸々端折った結果、ここに記載のやり方はあまりよろしくないやり方です。
それはWEBサーバとAPサーバという構成についてある程度知見があればわかる話ですが、ここでは避けます。
あくまで手段の一つ、中小規模のサイトではまずまずこれでもよいでしょうってところでお願いします。

試すのはこちらの画像を拝借しましょう
一応フリーアイコンと称されております。
https://twitter.com/_toki_s/status/1297399221117542402/photo/3


# 前回の続きを前提としているため、このディレクトリはもう存在しているものとします
cd /tmp/sample/
mkdir -p static/sample

# ダウンロード
curl -c 'https://pbs.twimg.com/media/EgFJtY0UYAEf0EC?format=jpg&name=medium' --output static/sample/icon.jpg




# sample/settings.py

# これは任意だけどgunicornを前提としているのでここでは修正対象
-ALLOWED_HOSTS = []
+ALLOWED_HOSTS = ['*']

# STATIC_URLの下あたりに追加
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')



# sample/urls.py


# 既存import文の近くに記載しておく
+from django.conf import settings
+from django.conf.urls.static import static

# こんな感じで既存の配列に加える感じ
urlpatterns = [
path('admin/', admin.site.urls),
-]
+] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)




# gunicornを起動

gunicorn sample.wsgi --bind 192.168.3.97:8000




後はブラウザで確認してどうか、って感じでしょうか。
http://192.168.3.97:8000/static/sample/icon.jpg

sample/static の中にあるディレクトリはすべてhttp://192.168.3.97:8000/static/からアクセス可能です。
今回は sample/static/sample/icon.jpg と配備したので http://192.168.3.97:8000/static/sample/icon.jpg となります。

■検索タグ
python3
Django==3.1
django

拍手

PR
1から構築する場合の手順なんてあっという間に忘れてしまうよね(;'∀')
ちょっとメモします。
ただし、本当にDjangoが単体で動くところまでです。
例によってMX Linuxで検証。
たぶんLinuxはそのまま、応用でWindowsも同じだと思います。


# MX Linux はpipがデフォで入っていない
sudo apt install python3-pip
# Django のインストール
sudo pip3 install django
# Django 組み込みサーバ(runserver)でもいいけど、gunicorn入れてみる
sudo pip3 install gunicorn

# sample というプロジェクトを作ってみる
cd /tmp
django-admin startproject sample

# サーバ起動
cd sample
gunicorn sample.wsgi
# サーバとしてならローカルのグローバルIP(状況による)を指定して起動もありです
# -> その場合ALLOWD_HOSTを変える必要があるけど
gunicorn sample.wsgi --bind 192.168.3.97

# curl でアクセス確認
# ブラウザがあるならブラウザでもいいと思います
curl http://localhost:8000/ 2>/dev/null | grep title





# 検索ワード
python3 django==3.1

拍手

MX Linuxというのが最近気になっちゃって…
debianベースということでUbuntuチックかなと、サーバを立ててみたものの、やや癖がありました。
標準リポジトリでも default-mysql-server というMySQLをインストールできるみたいです。
けれど今回はおおもとのMySQLに記載されているやり方でやってみようと思います。


sudo apt -y update
sudo dpkg --configure -a
sudo apt -y upgrade
# DL リンクは下記URLの「No thanks, just start my download.」というアンカーテキストにあります
# https://dev.mysql.com/downloads/file/?id=494003
wget 'https://dev.mysql.com/get/mysql-apt-config_0.8.15-1_all.deb'
sudo dpkg -i mysql-apt-config_0.8.15-1_all.deb
-> インストールするMySQLのバージョンを選択可能
sudo apt -y update
sudo apt -y upgrade
sudo apt -y install mysql-server
-> root パスワードを設定可能
sudo /etc/init.d/mysql start
-> 基本的には起動済みの幡豆
mysql -u root -p

拍手

テキストをリクエストすると加工して返してくれるみたいな処理をPython3.5*mod_wsgiで組んでみました。
もともとPythonでWEBアプリケーションを組む際はDjangoを使うことが多く、ごくごく普通にWSGIを使っていました。

今回はいろいろなシステムからの結合を考えてAPIでI/Fを整えたバッチシステムです。
システム統合と汎用性を重視した設計だったのですが、一部からもう少しスループットを向上したいと要望が。
単純にCPUコアを載せてみたところ…?

体感でほぼ変わらないとのこと。
うーん、あたしはインフラ屋とは違うんだけどなぁ(-_-;)



見てみたところ、なんと遊んでいるCPUコアがある!
しかも真面目にお仕事しているApacheは1つしかない…
これは驚愕の事実です
※ちなみにデーモンモードでvirtualhostを使用しています

これはすなわちDjangoアプリケーションでスループットを上げるにはエンベデッドモードかサーバをスケールアウトするしかないということです。
実にイケてない。
え?本当に?
おそらくデーモンモードは割り当てたプロセスグループ(WSGIProcessGroup)1つにつき1プロセスなんだと思います。
なので、VirtualHostを複数切って受ければ行ける?

試したところ、想定通りのうごきとなりました~♪
VirtualHostで組み込みモードが使えればいいのですが…
今のところできないんですよね…
※WSGIPythonHomeなどがVirtualHostセクションで使用できない

拍手

業務の都合上プロキシが必要になることがありまして。。。
よく参考にさせていただく、オープンプロキシのサイトを備忘録的に掲載させていただきます。

http://free-proxy.cz/ja/
http://lab.magicvox.net/proxy/
http://proxy.moo.jp/ja/
http://tools.rosinstrument.com/
http://www.cybersyndrome.net/plr6.html
http://www.gatherproxy.com/ja
https://us-proxy.org/
https://www.proxynova.com/proxy-server-list/
https://proxy-stock.ddns.net/

拍手

私がPythonを学び始めた2011年ころはほぼ日本語のドキュメントや記事はありませんでした。
いまはだいぶ豊富になりましたね。
それでもまだ機械学習などバッチ的要素での活躍が多くWEBはなかなか採用が見られません。
そのため、PythonでWEB開発を使用とすると意外に情報収集が困難だったりします。
なので個人的に役にたったよーって一覧を載せておきすね♪


(認証などのシステムで)ユーザの作成や変更など
https://docs.djangoproject.com/en/2.2/topics/auth/default/

formクラスの基本的な使い方
https://eiry.bitbucket.io/tutorials/tutorial/forms.html

formとmodelが対になっている場合のPOSTデータのDB登録
https://djangobrothers.com/tutorials/memo_app/form/

フォームの表示方法まとめ
https://narito.ninja/blog/detail/98/

ラジオボタンを設置
https://qiita.com/xKxAxKx/items/284abc565715f2283fec

inputタグのhidden
https://dot-blog.jp/news/django-modelform-field-hidden/


拍手

唐突にプログラムを作成してほしいという依頼が。
ちょこっと使いたいだけだから、過去に似たツールがあればそれでもいいとのこと。
確かに8年前くらいにそんなツール合ったような…

ってことで過去のツールでもいいよってなりました。
おそらくライブラリが足りないだろうから、それだけ入れれば動くんじゃないかなー、って楽観視。


実際動かしてみると。。。
    print e.message
          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(int e.message)?

ああ...orz
Python2系だ。。。(げんなり)

2系をインストールして、対応しようかしら?
ちょっと迷ったけど、800行くらいのソースなんだしprint文くらいかっこで括ろうよ!
というわけでprintを書き換えて再実行。

  File "C:\Users\s.ikota\Documents\000.develop\easy_crawler_rev3.4.0(開発中) - コピー\crawler.py", line 201
    raise UnicodeDecodeError, "Failed convert string."
                            ^
SyntaxError: invalid syntax
raiseの書き方が変わってる…
直して実行

    import urlparse
ModuleNotFoundError: No module named 'urlparse'

くっ!
import urllib.parse as urlparse に変えて実行。

今度は StingIO !
import io as StringIO


f.next()
↓
next(f)


raw_input()
↓
input('')

そろそろ心が折れてきそうだわ…
if isinstance(o, str):
    return o.encode('utf-8')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'bytes' object has no attribute 'encode'
ん?
これはあれね、2系はbytesのことをstrと呼び、strのことをunicodeと呼んでいたからね。
一瞬なんで?ってなったわ。

return len(filter(lambda x: x, arr_text))
Traceback (most recent call last):
  File "", line 1, in 
TypeError: object of type 'filter' has no len()
listで返らなくなったのよねー、filterとかmapとかさ。


と、いうことでこんな感じでした。
これはガチなシステムだったら2系からの移行は確かに躊躇するわね。

番外編。
with open(RES_FILE, "wb") as f:
2系のころはバイナリとして読み込んだ後、適宜unicode化するのが当たり前だったわね。
結局後続のdecode、encodeでコケるので、これもbをとるような修正をしました。

拍手

お客様要望によりFirewallは実施しないでほしいと受けた案件がありました。
理由は自社のIPがわからないから…
規模や、何らかの壁により情シスとうまく連携が取れない企業様はそれなりにいらっしゃいます。
強く説得したいところではありますが、今回はそのままにしました。
ですが…
案の定、ものすごいポートアタックを受けます。
そんな無法者はさすがにブロックしたほうがよいと判断し、ブロックすることにしました。
当方では下記IPから雑にsniffingを受けたのでブロックします。
とりあえず、IP制限は実施したいけど、日本以外全部、は大変だなとお考えの方など参考になれば幸いです。

103.89.89.205
109.248.9.9
111.230.192.23
112.85.42.0/24
113.108.72.2
115.238.245.0/24
115.88.201.58
116.31.116.10
118.123.15.142/24
12.133.183.226
122.226.181.0/24
123.249.27.172
125.212.207.205
125.65.42.0/24
142.93.22.237
149.202.10.227
165.84.191.236
180.76.176.4
182.61.44.11
193.70.6.197
201.235.245.224
202.126.46.39
221.217.48.187
46.188.16.55
5.188.10.156
51.223.47.100
58.218.92.33
61.184.247.0/24
61.184.247.2
81.192.31.134
94.23.145.124
95.156.31.74


検索タグ
セキュリティ、IP制限、iptables、ファイアウォール、firewall

拍手

とある案件でAPIを実装することになりました。
クライアント側とサーバ側でベンダー異なるのですが、サーバ側の実装を待たずしてクライアント側でテスト的にモックが欲しいとのこと。
Google先生に聞いてみたらRESTfulなAPIをサクッと作れるミドルウェアがあると聞いて!
nodeで実装されたJSON形式のファイルを取り扱えるみたい。
早速試してみました!!

# OSの確認
$ uname -a
Linux localhost 4.4.0-128-generic #154-Ubuntu SMP Fri May 25 14:15:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/debian_version
stretch/sid
# まず、環境を整えます
sudo apt install -y npm
sudo npm install -g json-server
ln -s /usr/bin/nodejs /usr/bin/node
npm install -g n
n stable
json-server -v
# ダミーデータを投入
cat << __ > db.json
{
    "prefecture": [
            {"id":1, "name": "北海道", "yomi": "ホッカイドウ"},
            {"id":2, "name": "青森県", "yomi": "アオモリケン"}
        ]
}
__
# そしてサーバを起動
json-server db.json --watch --port 80 --host 192.168.3.91&
# GETのテスト
curl http://192.168.3.91/prefecture
curl http://192.168.3.91/prefecture/1

# POSTのテスト
curl http://192.168.3.91/prefecture -d 'name=岩手県&yomi=イワテケン'
curl http://192.168.3.91/prefecture -d 'name=宮城県&yomi=ミヤギケン'

# DELETEのテスト
curl http://192.168.3.91/prefecture/3  -X DELETE
curl http://192.168.3.91/prefecture -d 'name=岩手県&yomi=イワテケン'
curl http://192.168.3.91/prefecture

# IDのインクリメントの法則を試してみる
curl http://192.168.3.91/prefecture/4  -X DELETE
curl http://192.168.3.91/prefecture/5  -X DELETE
curl http://192.168.3.91/prefecture

# 再びPOST
curl http://192.168.3.91/prefecture -d 'name=岩手県&yomi=イワテケン'
curl http://192.168.3.91/prefecture -d 'name=宮城県&yomi=ミヤギケン'
curl http://192.168.3.91/prefecture

なるほど、これなら簡単ね(*^^*)
ただ、POSTが必ずしも登録ではなく、リクエストの一環としてやってくることも多いのが少し悩ましいところね。

以上、JSON-Serverでした。

拍手

多くのデータを分散処理したいことが多々あります。
並列化は一筋縄でいかないことはシステムを組んでみようと考えたことがある人なら難易度は低くないことは容易に想像がつくと思います。
特に処理をプロセス間で重複させないためのシリアライズは手を焼く仕組みの一つです。
この話をメンバに相談すると必ずキューイングがやり玉にあがるのです。

そうキューイング信者が社内にいるのです…
何かとキューキュー騒ぐので、何もたいそれたシステムを導入しなくても実現できるんじゃない?
と思いまして、調べたところ、DBで簡単に実現できそうでした♪

参考:
https://lightgauge.net/database/sqlserver/962/

まず、キューとなるテーブルを作成します。
psql
DROP TABLE mq ;
CREATE TABLE mq (
    id serial, 
    message text, 
    primary key(id)
);
\q

次に、テスト用にキューを貯めていきましょう。
for i in $(seq 1000)
do
    value=''
    for i in $(seq 10)
    do
        value="$value ,('hoge')"
    done
    psql -c "INSERT INTO mq(message) VALUES('hoge') $value "
done


キューを払い出しつつ、キューを削除していきます。
DELETE FROM mq WHERE id = (SELECT id FROM mq WHERE pg_try_advisory_lock(tableoid::int, id) LIMIT 1) returning *;

ターミナルをいくつか立ち上げて、下記コマンドを投げまくってみます。
\rm /tmp/hoge
for i in $(seq 600)
do
    psql -c"DELETE FROM mq WHERE id = (SELECT id FROM mq WHERE pg_try_advisory_lock(tableoid::int, id) LIMIT 1) returning 'hoge', *;" >> /tmp/hoge
done

結果を確認します。
うまくシリアライズされていました。
grep DELETE hoge | sort | uniq -dc
   1189 DELETE 1


行ロックを取得しない版も投げてみます。
\rm /tmp/hoge
for i in $(seq 600)
do
    psql -c"DELETE FROM mq WHERE id = (SELECT id FROM mq LIMIT 1) RETURNING 'hoge', *;" >> /tmp/hoge
done

処理がシリアライズできていないので二重処理してしまい、後から処理したものは削除ができず、0件になっています。
grep DELETE hoge | sort | uniq -dc
     37 DELETE 0
   1138 DELETE 1

これでPythonのQueueクラスのようなキューイングシステムができました。

小~中規模程度にしか通用しなさそうですが、やれ、ミドルウェアが必要だの、
OSのバージョンアップが必要だの、大げさな話になるくらいならこれくらいライトに初めてもいいのではないでしょうか^^

拍手

Copyright ©  アナログを愛するデジタル生活館 All Rights Reserved.
* material by Pearl Box   * Template by tsukika

忍者ブログ [PR]