2018,江端さんの忘備録

■銀座のクラブに通えるようになることが、その人のステータスになる

- Going to attend the club of Ginza will be the status of that person

■ベンツを所有することが、その人のステータスになる

- Owning Benz will be the status of that person

■結婚式に、与党総裁からの祝電を貰えることが、その人のステータスになる

- getting a greeting from the president of the ruling party will be the status of that person

―― 「という感じが、よく分からん」と嫁さんに話していたところ、

When I talked to my wife "I cannot understand their feeling", she said to me,

嫁さん:「『ステータスを示す』ことが『目的』ではないのかもしれないよ」

Wife:" "Showing their status" might not be their purposes"

と言われました。

江端:「というと?」

Ebata:"What is it?"

嫁さん:「それらの行為は、自分の仕事の枠を広げる『人脈』のプラットフォームという『道具』なのかもしれない」

Wife: "These behaviors may be just "tools" of as a platform of personal network to extend their work."

-----

なるほど。

I see.

個人でできることは、知れていますが、他の人との協力関係が築けるのであれば、それは、価値のある『道具』になるかもしれません。

Personal activities must be limited, however, even if they can establish a cooperative relationship with other people, they might have valuable "tools".

しかし、そのように考えてみると、今のところ私には関係なさそうです。

But thinking about it, I don't have to care of it at all.

私にとって、その人を評価する『通貨』は何かと問われれば、―― 少くとも「人柄」「人徳」「優しさ」ではない。

What is my "currency" to evaluate that person is not at least "personality" "humanity" "kindness".

「趣味」でもないし、私に興味のない「知識」をどんなにひけらかされようが、私は評価しない。

It is not a "hobby", and I will not evaluate anyone who shows off "knowledge" that I am not interested in.

「信念」「思想」などは、論外です。

"Belief" "Thought" etc. are out of the question.

-----

私にとっての通貨は、―― 「技術力」ですね。

My currency is "technology power".

私にない「圧倒的な技術力」に対して、圧倒的な魅力を感じます。

I feel overwhelming charm about "overwhelming technical power" that I do not have.

だから、私にとって「与党党首からの結婚式の式典の電報」なんぞ、計算用紙にもならない、ただの紙っきれです。

So, for me, "the telegram of the wedding ceremony from the ruling party leader" is just a piece of paper that does not become a calculation paper.

私だったら、「従来の1000倍の高速化を実現する、解探索プログラムコード」が記載されている祝電の方がいいです。

I would rather to give me "the telegram of the wedding ceremony written "solution search program code that realizes 1000 times faster speed than in the past".

2023,江端さんの技術メモ

> uvicorn main:app --reload

main.py

import uvicorn
from fastapi import FastAPI, File, UploadFile

import shutil
import os

app = FastAPI()

@app.post("/files/")
async def file(file: bytes = File(...)):
    content = file.decode('utf-8')
    formatfile = content.split('\n')
    return {'filedetail': formatfile}

@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    if file:
        filename = file.filename
        fileobj = file.file
        #UPLOAD_DIR = os.getcwd() 
        #print(UPLOAD_DIR)
        #upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
        upload_dir = open(os.path.join("C:\\Users\\ebata\\fastapi6\\", filename),'wb+')
        shutil.copyfileobj(fileobj, upload_dir)
        upload_dir.close()
        return {"アップロードファイル名": filename}
    return {"Error": "アップロードファイルが見つかりません。"}



'''
@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    return {'filename': file.filename}
'''

クライアントは、こうなる。

前提は、C:\Users\ebata に dummy.txtがあること。
そして上記のmain.pyは、C:\Users\ebata\fastapi6にあること(まあ、そのへんは適当に変えて使って下さい)

 

C:\Users\ebata>curl -X POST http://127.0.0.1:8000/uploadfile/ -H 'accept: application/json' -H 'Content-Type: multipart/form-data' -F file=@dummy.txt;type=text/plain

クライアントプログラムは作成中

2023,江端さんの技術メモ

https://teratail.com/questions/8xzab7sat8gujj#reply-3jfh5txotuqxqb

の質問サイトに投げたものですが、ローカルでも作っておきます。

実現したいこと

TLS対応にしているGo言語のサーバを、Dockerコンテナの中から使えるようにしたい

前提

GO言語を使ってサーバを作っています。これらのサーバをDockerコンテナに格納して、運用しやすくしたいと考えております。

発生している問題・エラーメッセージ

Dockerコンテナに格納すると、https(×http)通信が使えません。

cert.pem、key.pemを使わない場合、http://127.0.0.1:18888で、ブラウザに"hello"メッセージがされますが、cert.pem、key.pemを使ってhttps://127.0.0.1:18888とした場合、「このサイトにアクセスできません」と表示されます。

該当のソースコード

GO言語

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
)

var url_host string

func handler(w http.ResponseWriter, r *http.Request) {
	dump, err := httputil.DumpRequest(r, true)
	if err != nil {
		http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
		return
	}
	fmt.Println(string(dump))
	fmt.Fprintf(w, "<html><body>hello</body></html>\n")
}

var addr = flag.String("addr", "127.0.0.1:18888", "http service address") // テスト

func main() {
	http.HandleFunc("/", handler)
	fmt.Println("url_host:", url_host)

	log.Println("start http listening :18888")

	var httpErr error
	if _, err := os.Stat("./cert.pem"); err == nil {
		if httpErr = http.ListenAndServeTLS(*addr, "./cert.pem", "./key.pem", nil); httpErr != nil {
			log.Fatal("No pem file with https error: ", httpErr.Error())
		}
	}
}

ちなみに、cert.pemと、key.pemは、"127.0.0.1","localhost"で通るように作ってあります。

ローカルネットワークにおける「オレオレ証明書」の作り方 "http: TLS handshake error from 192.168.0.22:59914: remote error: tls: unknown certificate"のエラーを、ようやく消せました

Dockerfile
#FROM golang:apline
FROM golang:1.16.3-alpine
WORKDIR /go
ADD . /go
CMD ["go", "run", "main.go"]

docker-compose.yml

version: '3'
services:
  app:
    build: .
    ports:
      - "18888:18888" # "ホストのポート:コンテナのポート"

試したこと

上記のmain.go のfunc main()を以下のようにしている場合は,http(×https)で通信できます。

func main() {
    var httpServer http.Server
    http.HandleFunc("/", handler)
    log.Println("start http listening :18888")
    httpServer.Addr = ":18888"
    log.Println(httpServer.ListenAndServe())
}

補足情報(FW/ツールのバージョンなど)

■Windows10上のDocker for Windowsを使用しています。
■Dockerコンテナを使わないで、 windowsのコマンドプロンプトから起動する場合は、"https://127.0.0.1:18888"は問題なく起動します。

で、頂いたご回答が以下の通り。

Dockerfile

#FROM golang:apline
FROM golang:1.16.3-alpine
WORKDIR /app
ADD . /app
CMD ["go", "run", "main.go", "-addr", ":18888"]

と最後の一行を、CMD ["go", "run", "main.go", "-addr", ":18888"]

とするだけでした。

で、以外な盲点が、

ブラウザのキャッシュを消去しないと、変更がブラウザに反映されない

だったりします。(何度も経験しているのに、これをよく忘れるんだよなぁ)

感想

散々、色々試したあげく、最初に頂いた、Dockerfileの内容に変更することで、無事問題を解決することができました。現在、Dockerの中で立ち上げたgoのサーバに対して、https://localhost:18888で表示されることを確認しました。

今後のサーバ立ち上げに関して、かなり有益な知見となりました(実サーバ運用では、ご指摘の内容を反映してリスクを回避したいと思います)。 この度は、誠にありがとうございました。

以上

未分類

ありふれているけど、いつの時でも頭を抱える状況に、今回も頭を抱えています。

It's common, however, it has made me annoyed, and I am annoyed now.

今回は、chkdskでも、復旧できませんでした。

This time, "chkdsk" didn't save me.

「chkdsk f: /f」という掛け軸が販売されるのであれば、今、直ぐにでも購入する準備があります。

各種の市販ツールも試してみたのですが、ダメでした。

I tried various commercial tools, but they were in vain.

2021/12,江端さんの技術メモ

■Windows Updateの後は、絶対にWindows Defenderの設定をしなおせ

■Windows Updateがなくても、「重い」と思ったら、Windows Defenderの設定を見ろ → 勝手に設定されているぞ

昨日から「Windows10が重くて使えない」という状態が続くので、タスクマネージャーを見てみたら、Antimalware Service Executableのメモリ消費量がシャレにならないくらい大きいことが分かりました。

メモリ/ディスクを使用する重いAntimalware Service Executableの対処法【停止も】

対処2: Windows Defenderのタスクスケジューラで設定を変更する

  1. 「Windowsマーク」をクリックし、「Windows管理ツール」→「タスクスケジューラ」の順にクリックします。
  2. タスクスケジューラの画面が表示されたら、左ペインで「タスクスケジューラライブラリ」をクリックしてツリーを展開します。
  3. 「Microsoft」→「Windows」→「Windows Defender」の順に展開します。
  4. 「Windows Defender」を選択して、右側にある「Windows Defender Scheduled Scan」をダブルクリックします。
  5. 画面が表示されたら「全般」タブを選択します。
  6. 画面下部にある「最上位の特権で実行する」のチェックを以下の4つの項目全部で外します。(つまり、以下の処理を項目ごとに、全部で4回やる、ということです)
  7. 「最上位の特権で実行する」のボタンが押せないので、「プロパティ」を押す

    ここからチェックを外す

  8. 「OK」をクリックします。

とりあえず、これで「Windows10が重くて使えない」状態は解消できるようになりました。


ノートPCも恐しく遅くて使えないので、この方法を試しました。現在、ちんたらと再起動処理をしているようですので、多分改善すると思います。

あやうくノートPCを廃棄してしまうところでした。

 

2023,江端さんの技術メモ

1 目的

すぐに環境やらコード(の場所)やらを忘れるので、自分の為にメモを残す

2 簡単なfastapiの環境とコード

私の環境では、c:\users\ebata\fastapi1,2,3,4,5あたりにある。

2.1. 最新のPIPをアップグレードする

> pip install --upgrade pip
> python -m pip install --upgrade pip
> python3 -m pip install --upgrade pip

のいずれかでできる。

2.2. uvicorn, fastapi, pydantic, pandas, requests, jsonのモジュールをインストールする

> pip3 install fastapi
> pip3 install uvicorn[standard]

は必須だが、後はプログラムを動かせば、プログラムの方から、インストールを指示されると思うので大丈夫(だろう)。

2.3. uvicornを起動する

> uvicorn index:app --reload

これで、自動的に"index.py"が動き出す。

2.4. クライアントを起動する

> python request.py

で、起動を確認する。

以上

3. ソースコード

3.1. index.py

# https://miseruit.com/2022/07/18/post-2939/

from fastapi import FastAPI
from pydantic import BaseModel
import pandas

class Item(BaseModel):
    ID: str
    Name: str
    Class: str

app = FastAPI() #インスタンスを作成

User_list =[
    {"ID":"M001","Name":"Takashi","Class":"A"},
    {"ID":"M002","Name":"Hanako","Class":"A"},
    {"ID":"M003","Name":"Hiroshi","Class":"B"},
    {"ID":"M004","Name":"Kyoko","Class":"B"},
    ]

# joson_normalize関数を用いてJsonデータをDataFrame型に変換します。
df = pandas.json_normalize(User_list)

# Get /Users/ : 全件取得
# Get /Users/{ID} :特定のIDのみ取得
# POST /Users/ :ユーザの登録
# DELETE /Users/{ID} :ユーザの削除

# curl http://localhost:8000/Users/
@app.get("/Users/")
async def users():
    return User_list

# curl http://localhost:8000/Users/M003
@app.get("/Users/{u_id}")
async def users(u_id:str):
    return list(filter(lambda item : item['ID']==u_id, User_list))

# Windowsの場合 
# {"ID":"M005","Name":"Aya","Class":"C"}]を追加する
# curl -X POST -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ID\":\"M005\", \"Name\":\"Aya\", \"Class\":\"C\"}" http://localhost:8000/Users/

@app.post("/Users/")
async def users(user: Item):
    User_list.append({"ID": user.ID,"Name":user.Name,"Class":user.Class})
    return User_list

# curl -X DELETE -H "accept: application/json" http://localhost:8000/Users/M003
@app.delete("/Users/{u_id}")
async def users(u_id:str):
    global df
    df = df.drop(df.index[df["ID"]==u_id])
    return df.to_json(orient='records')

3.2. request.py

import requests
import json

# テスト
#url = 'https://wp.kobore.net/'
#response = requests.get(url)
#print(response.text)

#print()

print("-----start of get(1)")

# curl http://localhost:8000/Users/ と同じ機能を実施
r = requests.get('http://localhost:8000/Users/')

print(r.url)
print(r.status_code)
print(r.text)
print(r.json())

print("-----end of get(1)")

print()

# curl http://localhost:8000/Users/M003 と同じ機能を実施

print("-----start of get(2)")

r = requests.get('http://localhost:8000/Users/M003')

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())
print("-----end of get(2)")

print()
print("-----start of delete")
# curl -X DELETE -H "accept: application/json" http://localhost:8000/Users/M003と同じ機能を実施
r = requests.delete('http://localhost:8000/Users/M003')

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())

print("-----end of delete")
print()

# curl -X POST -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ID\":\"M005\", \"Name\":\"Aya\", \"Class\":\"C\"}" http://localhost:8000/Users/ と同じ機能を実現
# {"ID":"M005","Name":"Aya","Class":"C"}]を追加する

headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
json_payload = '{"ID":"M005","Name":"Aya","Class":"C"}'  # ここで100回くらいのパターンを試したぞ

print("headers:",headers)
print("payload:",json_payload)

#r = requests.post('http://localhost:8000/Users/',headers=headers, params=payload)
#r = requests.post('http://localhost:8000/Users/', headers=headers,params=json.loads(payload))
r = requests.post('http://localhost:8000/Users/', headers=headers, data=json_payload)

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())

2023,江端さんの技術メモ

結論から先に言うと

json_payload ='{"ID":"M005","Name":"Aya","Class":"C"}'
'"が付いているかどうか、だったというオチでした。

pythonでFastAPIを試す

のように、pythonでFastAPIを使って、外部と内部のインターフェースのテンプレートを作るというのが、目下の課題でした。
多くのサンプルプログラムがあったのですが、私はhttpのGET/POSTができれば十分だったので、他のことは忘れて、そのポイントのみに絞って、ネットを探し回りました。
まずは、FastAPIを受ける側(サーバと言えるのかな)のプログラムは、

Python | FastAPIでAPI作成 ~その6:DELETEでデータ削除 & Pandas活用

を参考(というかコピペ)させて頂きました。

以下のコードを、私の場合はC:\Users\ebata\fastapi4に、index.pyという名前で置きました。
# https://miseruit.com/2022/07/18/post-2939/

from fastapi import FastAPI
from pydantic import BaseModel
import pandas

class Item(BaseModel):
    ID: str
    Name: str
    Class: str

app = FastAPI() #インスタンスを作成

User_list =[
    {"ID":"M001","Name":"Takashi","Class":"A"},
    {"ID":"M002","Name":"Hanako","Class":"A"},
    {"ID":"M003","Name":"Hiroshi","Class":"B"},
    {"ID":"M004","Name":"Kyoko","Class":"B"},
    ]

# joson_normalize関数を用いてJsonデータをDataFrame型に変換します。
df = pandas.json_normalize(User_list)

# Get /Users/ : 全件取得
# Get /Users/{ID} :特定のIDのみ取得
# POST /Users/ :ユーザの登録
# DELETE /Users/{ID} :ユーザの削除

# curl http://localhost:8000/Users/
@app.get("/Users/")
async def users():
    return User_list


# curl http://localhost:8000/Users/M003
@app.get("/Users/{u_id}")
async def users(u_id:str):
    return list(filter(lambda item : item['ID']==u_id, User_list))


# Windowsの場合 
# {"ID":"M005","Name":"Aya","Class":"C"}]を追加する
# curl -X POST -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ID\":\"M005\", \"Name\":\"Aya\", \"Class\":\"C\"}" http://localhost:8000/Users/

@app.post("/Users/")
async def users(user: Item):
    User_list.append({"ID": user.ID,"Name":user.Name,"Class":user.Class})
    return User_list

# curl -X DELETE -H "accept: application/json" http://localhost:8000/Users/M003
@app.delete("/Users/{u_id}")
async def users(u_id:str):
    global df
    df = df.drop(df.index[df["ID"]==u_id])
    return df.to_json(orient='records')
このプログラムは、メモリ上の名簿を検索(GET)、追加(POST)、削除(DELETE)するものです。

C:\Users\ebata\fastapi4> uvicorn index:app --reload

で起動します。
多分、プログラムの方から、「pipでxxxxを入れろ」と文句を言ってきますので、大人しく従います。
プログラム中に記載されている、curlのコマンドを使うとFastAPIの動作を確認できます。
さて、このプログラムで基本動作は確認できますが、基本的にクライアントのプログラムの叩き台がなければ、使えません。モジュールプログラムの中から、curlのコマンドを発行しろというのも乱暴な話です。
ですので、サクッとクライアント(というかFastAPIのアクセス用のテストプログラム)を作成してしまうと思ったのですが、ここで嵌りました。
先ずは、以下のコードをrequest.pyという名前で、C:\Users\ebata\fastapi4に置きました。
(以下のファイルは、動きたてのコードを修正せずに、汚いままで展開しています)
import requests
import json

# テスト
#url = 'https://wp.kobore.net/'
#response = requests.get(url)
#print(response.text)

#print()

print("-----start of get(1)")

# curl http://localhost:8000/Users/ と同じ機能を実施
r = requests.get('http://localhost:8000/Users/')

print(r.url)
print(r.status_code)
print(r.text)
print(r.json())


print("-----end of get(1)")

print()

# curl http://localhost:8000/Users/M003 と同じ機能を実施

print("-----start of get(2)")

r = requests.get('http://localhost:8000/Users/M003')

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())
print("-----end of get(2)")


print()
print("-----start of delete")
# curl -X DELETE -H "accept: application/json" http://localhost:8000/Users/M003と同じ機能を実施
r = requests.delete('http://localhost:8000/Users/M003')

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())

print("-----end of delete")
print()



# curl -X POST -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ID\":\"M005\", \"Name\":\"Aya\", \"Class\":\"C\"}" http://localhost:8000/Users/ と同じ機能を実現
# {"ID":"M005","Name":"Aya","Class":"C"}]を追加する

headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
json_payload = '{"ID":"M005","Name":"Aya","Class":"C"}'  # ここで100回くらいのパターンを試したぞ

print("headers:",headers)
print("payload:",json_payload)

#r = requests.post('http://localhost:8000/Users/',headers=headers, params=payload)
#r = requests.post('http://localhost:8000/Users/', headers=headers,params=json.loads(payload))
r = requests.post('http://localhost:8000/Users/', headers=headers, data=json_payload)

print(r.url)

print(r.status_code)
print(r.text)
print(r.json())
で、
C:\Users\ebata\fastapi4> python request.py
にて、GETとDELETEは問題なくサクっと動いたのですが、POSTだけが思うように動かない
{'detail': [{'loc': ['body'], 'msg': 'value is not a valid dict', 'type': 'type_error.dict'}]}
{"detail":[{"loc":["body"],"msg":"field required","type":"value_error.missing"}]}
エラー番号422
やらが、ワラワラと出てきて、頭を抱えました。
色々検索して調べると『こうやればいい』というアドバイスだけして、サンプルコード(1行で足る)を残さない奴が、世界中には山ほどいます(アドバイスではなく、コードを残して欲しい)。
のコードを真似て、ようやく動かすことができました(本当に助かりました)。
とりあえず、これでサーバとクライアントの対(つい)が完成し、実プログラムに展開できる準備ができたと思います。

以上

2023,江端さんの忘備録

本日、リモート環境で打ち合わせをしている最中に、比較的大きめの地震が発生しました。

During a remote meeting, a relatively big earthquake occurred.

が、打ち合わせはそのまま問題なく進んでいるので、『いちいち地震を気にしないで会議を進めるのだ』と思っていました。

However, the meeting continued without any trouble, I thought "They don't care about earthquakes"

ところが、3秒くらい経過したところで、「あ、揺れている」「比較的大きいですね」という声がチラホラ聞こえてきました。

After about three seconds, the voice "Oh, it's shaking," or "It's relatively big" were coming, so I thought

―― 生れてはじめて、地震波の存在をリアルに実感した

"For the first time in my life, I really felt the existence of earthquake waves"

と思いました。

"巨大地震の発生直後、飛行場の管制官が、離陸の最中にあった旅客機に停止指示を出さずに、空に逃がすシーン"

-----

ただ、Twitterで震源地情報などを調べると、どうも、違和感がある。

However, I felt a sense of discomfort, when I looked up the epicenter on Twitter.

私の住んでいるところが、一番震源地より遠いはずです。

My location must be far from the epicenter, I thought.

私の考えた、仮説の一つは、『他の人の(高価な)家は免震構造が頑強であるが、私の(高価でない)家は敏感にP波(初期微動)を感じられる』です。

One of my hypotheses is that "other member's houses are expensive and robust seismic isolation structures, but my house is not expensive and can feel P-waves (initial microtremors) sensitively.

あまり愉快な仮説ではありませんが。

Anyway, it is not a very pleasant hypothesis.

未分類

なんでこれが

FROM golang:1.16.3-alpine
WORKDIR /go
ADD . /go
# CMD ["go", "run", "main.go","-addr" ":18888"]
# CMD ["go", "run", "main.go","-addr" ":18888"]
# CMD ["main.exe"]

こうなる?

わからん・・・

2023,江端さんの忘備録

私は、自分のWebサイトをDB化しています ―― GoogleエンジンとWordPressの検索機能を使っているだけですが。

I use my website as DataBase, using just the Google search engine and search functions of WordPress.

これ結構便利です。

This is really useful.

「○○についてネタが欲しい」と思った時に、すぐに探し出せるからです。

Whenever I want to tell a story about a specified theme, I can find it soon.

Amazon 恐るべし。

-----

今日も会社で、あるテーマについて投稿しなければならなかったのですが、数秒でネタを見つけました。

Today I was ordered to submit a short story about a specific theme, and I could find it in a few seconds.

まあ、ネタの使い回しもあるので、何度も同じ話を聞かされている人もいるでしょうが ―― まあ、そこは、諦めて下さい。

Well some people should hear my story again and again, I ask them to give up.

-----

なんだかんだ言って、私のWebの創立は、1993年です ―― 創業30年の老舗Webサイトです。

Anyway, my Web establishment was founded in 1993 -- a 30-year old Web site.

まあ、規模的には「和菓子屋」というよりは「駄菓子屋」ですが ――

Well, in terms of scale, it's more of a "candy store" than a "wagashi ya" -- however,

それでも歴史だけに着目すれば、AmazonやGoogleなどのGAFAなんぞは、小僧のようなものです。

Still, if you focus only on history, GAFAs like Amazon and Google are like little boys.

決して、負け惜しみではありません。

By no means is this a sore loser?