あると便利かもしれないスニペット集
あると便利かもしれないものたち
みなさんこんにちは、ALH開発事業部のREIYAです。
かゆいところに手が届くようなパーツをまとめてみました。
もちろん場面や人によると思いますがぜひご一読ください。
今回の記事では以下だけです。今後にご期待ください。
※一応言語ごとにまとめてますが、やっていることはバラバラなので許してね
Docker
Dockerfile
思うにイメージレイヤの最適化が拙かった時代のせいで私含めコマンドワンライナー芸人いまだに多いし、マルチステージビルドでバグらせることあるから全人類Dockerfileの書き方統一して欲しい
FROM python:3.11.4-slim-bullseye
WORKDIR /asset
COPY ./app /asset/app
RUN cd app \
&& python -m pip install -U pip \
&& python -m pip install -r requirements.txt \
&& chmod 777 some_file
CMD ["python", "app/server.py"]
pod監視
podを眺めておきたい時用
# とにかくみる
watch -n 1 -d kubectl get pod
# 全pod名
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
番号指定で入る
環境によって動かないので注意
no=3
tmp=$(kubectl get pods -o jsonpath='{.items[$no].metadata.name}')
kubectl exec -it $tmp /bin/bash
docker単品
# ビルドタグ付け起動
cd ~/パス \
&& docker build -t コンテナ名:latest . \
&& docker images | grep -e 'コンテナ名' -e 'latest' | awk '{print $3}' | xargs -I{} docker run {}
# ポート結びつけ
cd ~/パス
sudo docker build -t コンテナ名:latest .
sudo docker run -p 8080:8080 コンテナ名:latest
# host : container
# いろいろ操作
sudo docker ps -a
sudo docker stop {running container id}
sudo docker rm {id1} {id2} ...
sudo docker images
sudo docker rmi {id1} {id2} ...
# pullからワンライナー
git pull \
&& sudo docker build -t コンテナ名:latest . \
&& sudo docker run -d -p 8080:8080 コンテナ名:latest
docker単品のバインドとかする系
docker build -t IMAGENAME:latest . \
&& docker run \
--name NAME \
-d \
-p 8080:8080 \
-v "$(pwd)/../フォルダ:/asset/どっか" \
NAME:latest
# コンテナ停止 + 削除 (コンテナ名重複を防ぐ)
docker stop $(docker ps -aq -f name=NAME)
docker rm $(docker ps -aq -f name=NAME)
# 停止コンテナ全削除 + <none>なイメージ全削除
docker container prune
docker rmi $(docker images -f "dangling=true" -q)
Java
mutex
昨今は手動でやることあんまないかもですが、ふと排他したい時に便利。
public static void exclusive(Consumer<String> job, String procNm) {
File file = new File("ロックファイルパス");
try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);) {
FileLock lockedObject = channel.tryLock();
job.accept(procNm);
lockedObject.release();
} catch(OverlappingFileLockException e) {
} catch(IOException e) {
}
}
Function作る
型が多いとこんがらがりますよね。コピペしていきましょう
@FunctionalInterface
private interface MyFunc<T, S, U> {
void exe(T e1, T e2, S e3, U e4);
}
やけくそstream
中間と終端とりあえず書きまくっておいて必要なとこだけにしたらいい。
IntStream.rangeClosed(1, 10).boxed().forEach(System.out::println);
Arrays.asList("a").stream()
.filter(v -> "constant".equals(v))
.filter(predicate)
.map(Entity::getValue)
.map(v -> {
return v;
})
.peek(System.out::println)
.flatMap(l -> l)
.sorted()
.forEach(v -> {});
.collect(Collectors.joining(","));
.collect(Collectors.toList());
.collect(Collectors.toMap(e -> e.getId(), e -> e,
(l, r) -> r // 重複時後勝ち
,));
,LinkedHashMap::new)); // 順序付き
.collect(Collectors.groupingBy(Entity::getId, Collectors.mapping(Entity::getName, Collectors.toList())));
mapループ
意外と書くことが多い気がする
for (Entry<String, String> e : mp.entrySet()) {
e.getKey();
e.getValue();
}
本当はこう書きたい。JSとかCならいけます
for (auto &&[key, val] : map) {
}
スレッドセーフカウンタ
スレッドごとに持つだけ。カウンタでなくてもいい
private ThreadLocal<Integer> threadSafeCnt = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 1;
}
};
private void dfs() {
int cnt = threadSafeCnt.get();
System.out.println("いま" + cnt + "週目");
if (cnt == 5) {
threadSafeCnt.set(1);
return;
}
threadSafeCnt.set(cnt++);
dfs();
}
dfs();
スレッドセーフリスト
追加削除はこれで同期される
List<String> list = Collections.synchronizedList(new ArrayList<String>());
Python
lambda
ラムダが書きにくい言語って結構多い印象
odd = lambda v: v & 1
print([v for v in filter(odd, range(10))])
回数だけループ
for _ in [0] * 3: # どうでもいいがこっちのが早いらしい
print("ok")
for v in range(3): # 同じこと
print("ok")
デコレータ
たまにこんがらがるので。
import functools
def decorator_template():
def some(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# do something
return func(*args, **kwargs)
wrapper.__name__ = func.__name__
return wrapper
return some
lower_bound
upperはrightだね
import bisect
prime = [2, 3, 5, 7, 11, 13, 17, 19]
print(bisect.bisect_left(prime, 11)) # 4
# x以下の最大
def ika(arr, x):
i = bisect.bisect_right(arr, x)
if i:
return a[i-1]
pandas
結構忘れるのでまとめておきましょう。
接続系はプールしてるかなどで変わるのでよしなに。
def select(query, data_json):
"""SELECT as DataFrame
:param string SQL query
:param json Binding Parameters JSON
:return DataFrame
"""
return _read(_select, query, data_json)
def _select(con, query, data_json):
c = con.cursor()
q = c.execute(query, data_json)
cols = [column[0] for column in q.description]
results = pandas.DataFrame.from_records(data=q.fetchall(), columns=cols)
c.close()
return results
def insert(table, df_json):
"""INSERT DataFrame
:param string Table Name
:param json DataFrame JSON such as [{'columname': 'value'}]
"""
_exe(_insert, table, df_json)
def _insert(con, table, df_json):
pandas.DataFrame(df_json).to_sql(table, con, if_exists='append', index=False)
def _get_db():
"""Open connection
"""
con = sqlite3.connect(なにか)
return con
def _read(func, *args):
"""read & close
"""
con = _get_db()
res = func(con, *args)
con.close()
return res
def _exe(func, *args):
"""execute & commit
"""
con = _get_db()
res = func(con, *args)
con.commit()
con.close()
return res, con
def delete(sql, json):
con = _get_db()
con.execute(sql, json)
con.commit()
con.close()
使い方サンプル
query = 'SELECT id FROM table WHERE name like :name'
args = dict(name='%test%')
df = select(query, args)
df.iat[0, 0] # 0行目0列目
res = df.to_json(orient='records')
obj = json.loads(res) # if empty, string "[]"
sqlite前提でもっと簡潔に
import sqlite3
import pandas as pd
def _get_db():
return sqlite3.connect("DBファイルパス")
def select(query, data_json):
con = _get_db()
cur = con.cursor()
q = cur.execute(query, data_json)
res = pd.DataFrame.from_records(data=q.fetchall(), columns=[col[0] for col in q.description])
cur.close()
con.close()
return res
def get(query, cols):
con = _get_db()
cur = con.cursor()
q = cur.execute(query)
res = pd.DataFrame.from_records(data=q.fetchall(), columns=cols)
cur.close()
con.close()
return res
def exe(sql, json):
con = _get_db()
con.execute(sql, json)
con.commit()
con.close()
使い方
import json
from どこか import ふぁいる as sql
def sample():
# select 1行1列
query = "SELECT id FROM table WHERE val = :val"
df = sql.select(query, {"val": 10})
_ = df.iat[0, 0]
# select 全部
query = "SELECT id, name, val FROM table WHERE val = :val"
df = sql.select(query, {"val": 10})
res = df.to_json(orient='records')
_ = json.loads("[]" if res is None else res)
# カスタムquery
query = """
WITH some AS (
SELECT some FROM table LEFT JOIN AAA ...
)
SELECT aaa, aaa, ... FROM table
INNER JOIN some sub ON table.id = some.id
"""
col = ["id", "name", "some", ..... ]
res = sql.get(query, col).to_json(orient='records')
# insert
# update
# delete
query = "DELETE table WHERE id = :id"
sql.exe(query, {"id": 5})
Base64+json
Base64変換でJSON連携する際のトラップで、PythonでBase64変換すると「'」などが入りJSONが壊れる。
import base64
import json
request_str = 'この文字列をBase64変換した状態で送りたい'
# str -> bytes -> base64 -> str
data_bytes = bytes(request_str, 'utf-8')
data_encode_bytes = base64.b64encode(data_bytes)
data_encode_str = data_encode_bytes.decode('utf-8')
request_dict = {
'data': data_encode_str
}
Go
起動とか
goじゃなくてshellですが...
直起動してるならポートでkillしてpullからのあげ直しをデタッチみたいなことしますよね。
# run
go run .
# checkport
lsof -P -i:8080
kill {PID}
# sequence
lsof -P -i:8080 | awk 'NR==2 {print $2}' | xargs -t -I{} kill {} && git pull && go build && nohup ./appname &
レシーバ用意
// struct def
type ko struct {
oya oya.Ko
}
type Ko interface {
Create(c *gin.Context)
}
func NewKo() Ko {
return &ko{sql.KoIni()}
}
// Imprementation
func (ko *ko) Create(c *gin.Context) {
// some
}
WebSocket
GinとMelodyでwebsocketしたいとき。
というかWebSocketは大体全部同じ感じになるので言語関係なくこれみたらいいと思う
package some
import (
"encoding/json"
"log"
"strconv"
"strings"
"sync"
"github.com/gin-gonic/gin"
"github.com/olahol/melody"
)
var m *melody.Melody
func WSIni() {
m = melody.New()
lock := new(sync.Mutex)
// on connected
m.HandleConnect(func(s *melody.Session) {
log.Printf("#### websocket connection open. [session: %#v]\n", s)
lock.Lock()
// 部屋idみたいなのがURLにあるとする
reqUris := strings.Split(s.Request.URL.String(), "/")
roomId := reqUris[len(reqUris)-1]
i, _ := strconv.Atoi(roomId)
msgs := // 部屋iのメッセージを取得する
jsonstring, err := json.Marshal(msgs)
if err != nil {
log.Fatal(err.Error())
}
s.Write(jsonstring)
lock.Unlock()
})
// on disconnected
m.HandleDisconnect(func(s *melody.Session) {
message := "#### websocket disconnected."
s.Write([]byte(message))
log.Printf("#### websocket connection close. [session: %#v]\n", s)
})
// on message
m.HandleMessage(func(s *melody.Session, msg []byte) {
lock.Lock()
// 部屋idみたいなのがURLにあるとする
reqUris := strings.Split(s.Request.URL.String(), "/")
roomId := reqUris[len(reqUris)-1]
i, _ := strconv.Atoi(roomId)
// insert reqeust
var req なんらかのモデル
if e := json.Unmarshal(msg, &req); e != nil {
log.Fatal(e.Error())
}
userid, _ := strconv.Atoi(req.UserId)
DBに登録(i, userid, req.Msg)
// 今のメッセージを、同じ部屋の全員に送る
sessions, err := m.Sessions()
if err != nil {
log.Fatal(err.Error())
}
for _, v := range sessions {
uri := strings.Split(v.Request.URL.String(), "/")
joindroomId := uri[len(uri)-1]
// broadcast only same room (including me)
if roomId == joindroomId {
v.Write(msg)
}
}
message := string(msg)
log.Printf("[accept message]:%s", message)
lock.Unlock()
})
}
func MsgSync(c *gin.Context) {
m.HandleRequest(c.Writer, c.Request)
}
おわり
だいぶ統一感ないですが許してください。
他言語も別記事で出します。
ALHについて知る
↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓
↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓
↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓