ひとりごとの作業記録です。
0.今回のゴール
下記のような階層のプロジェクトを作成したい。
project/
│
├── frontend/ # Vue.jsアプリケーション
│ ├── src/
│ ├── public/
│ ├── package.json
│ └── ...
│
├── backend/ # Flaskアプリケーション
│ ├── app/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── ...
│ ├── venv/
│ ├── requirements.txt
│ └── run.py
│
└── README.md
その他の要件
・エディタには「VSCode」を使う。
・frontendは「vuejs」、backendは「python」フレームワークは「flask」
・frontendとbackendは「REST API」でやりとりする。
・開発環境は「MacOS Sequoia 15.2」
・pythonとかnodeとかVSCとか入ってる
1.projectフォルダを作成
mkdir project
うむ。これは当然問題はない。
2.フロントエンド作成工程
次にフロントエンドの階層を作っていこう。
今回フロントはvuejsだ。
2-1.プロジェクトを作成
mkdir frontend
cd frontend
vue create .
>Default (Vue 3) (babel, eslint) を選ぶ
npm install axios
「REST API」を使うので、とりあえず「axios」を入れてる。
ただそれだけだ。深い意味はない。
2-2. App.vue作成
テストだから、なんでもいい。
frontend/src/App.vue
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
message: '',
};
},
async created() {
try {
const response = await axios.get('http://localhost:5000/api/hello');
this.message = response.data.message;
} catch (error) {
console.error('Error fetching data:', error);
}
},
};
</script>
よし。ひとまずOK。
つぎはバックエンドだ。
3.バックエンド作成工程
バックエンドはflaskを使う。
3-1.ptyhonバージョン確認
そういえば、pythonのバージョンってどうなってだろう?
python --version
Python 3.11.4
下記を参照見てみると・・・。
アップデートの余地ありだな。
3.11.11にアップデートしよう。
pyenv install 3.11.11
pyenv global 3.11.11
python --version
Python 3.11.11
よし。次だ。
3-2.仮想環境の作成
ひとまず「venv」で行く。
python -m venv venv
source venv/bin/activate
まぁ、こんなもんだろう。
3-3.Flaskインストール
flaskをインストールだ
pip install flask
1)問題発生!
pip install flask
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/flask/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/flask/
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/flask/
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/flask/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/flask/
Could not fetch URL https://pypi.org/simple/flask/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/flask/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping
ERROR: Could not find a version that satisfies the requirement flask (from versions: none)
ERROR: No matching distribution found for flask
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping
なんじゃこりゃ?
2)原因調査
このエラーは、PythonインタプリタでSSLモジュールが利用できないため、
pipがHTTPS接続を確立できず、パッケージのダウンロードに失敗していることを示しています。
なるほど。
OpenSSLがロードできてないのか。
てか、本当か?
やってみなけりゃわからない。
python -c "import ssl; print(ssl.OPENSSL_VERSION)"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/mac-user/.pyenv/versions/3.11.11/lib/python3.11/ssl.py", line 100, in <module>
import _ssl # if we can't import it, let the error propagate
^^^^^^^^^^^
ImportError: dlopen(/Users/mac-user/.pyenv/versions/3.11.11/lib/python3.11/lib-dynload/_ssl.cpython-311-darwin.so, 0x0002): Library not loaded: /opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib
Referenced from: <5FC80B1A-4E22-3C4B-A4C2-871CA752C6F3> /Users/mac-user/.pyenv/versions/3.11.11/lib/python3.11/lib-dynload/_ssl.cpython-311-darwin.so
Reason: tried: '/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/lib/libssl.1.1.dylib' (no such file), '/usr/lib/libssl.1.1.dylib' (no such file, not in dyld cache)
おおぅ・・・。
確かにできない。
疑って悪かった・・・。
となると・・・
PythonがSSLモジュール(_ssl)を初期化する際に、
必要なOpenSSLライブラリ(libssl.1.1.dylib)が見つからないために発生
している、ということだね。
・・・いやいやいやいやいや・・・。
でもさ・・・でもさ・・・。
OpenSSLって入ってるよね?
openssl version
OpenSSL 3.4.0 22 Oct 2024 (Library: OpenSSL 3.4.0 22 Oct 2024)
ほら!
この通り、OpenSSL3系が入っている。
にもかかわらず、なぜか「1.1系」を要求されているの???
おかしくね?
まぁ、よくわからないが
言われるがままに「1.1」をいれてみる。
「えい!」
brew install openssl@1.1
==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Auto-updated Homebrew!
==> Updated Homebrew from 55f399c10d to 55475cb11a.
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
binocle c2patool cargo-cache diary json2hcl
==> New Casks
spectrolite
You have 9 outdated formulae installed.
Error: openssl@1.1 has been disabled because it is not supported upstream! It was disabled on 2024-10-24.
エラーになった。
はっはーん。1.1系はもうダメだってことだな。
そりゃそうだろ。
っていうか、なんだこれ?
「1.1系を入れろ」って言われたから入れたのになにこの仕打ち。
3)状況がよくわからなくなったので再度整理する
そもそもやりたいことって?
venvで作った仮想環境に、パイソン3.11.11にFlaskを入れたい。
そうだよ。そうだよ。
やりたいことはこれだよ。
「opensslのインストールがどうのこうの・・・」
って罠に引っかかってると、そのまま沼にハマる。
やべぇ。
でかしたぞ、俺!
4)再度、原因調査(ver. ChatGPT o1)
ChatGPT o1に質問。
「venvで作った仮想環境に、パイソン3.11.11にFlaskを入れたいのだけど、
こんなエラーがでて困ってるんだよ。
でもさぁ、openssl3は入ってるのに、openssl1系を求められるとかも意味わかんないし。
本来の目的を達成するためには、どうしたらいい?」
最もよくある原因は、Python のビルド/インストールが SSL ライブラリを正しく取り込めていないことです。
- macOS の場合、システム標準の OpenSSL が古い/または LibreSSL が使われているなどの理由で、Python が SSL 関係のモジュールをうまく組み込めないケースがよくあります。
- 「
openssl version
では 3.x が入っている」と表示されても、Python が実際にその OpenSSL を見つけてリンクしているかは別問題です。 - 一部のインストール方法(例: Homebrew から Python を入れた、pyenv でコンパイルした等)によっては、Python がビルドされる際に必要な OpenSSL のヘッダやライブラリが適切に読み込まれず、SSL サポートが無効化された状態でインストールされることがあります。
ほほう、なるほど。
なんとなく現在の状況が理解できたぞ。
ならば・・・
5)諸々インストールし直す
これが一番早い気がする。
brew update
brew install openssl@3
brew info openssl@3
==> openssl@3: stable 3.4.0 (bottled)
Cryptography and SSL/TLS Toolkit
https://openssl-library.org
Installed
/opt/homebrew/Cellar/openssl@3/3.4.0 (7,236 files, 33.4MB) *
Poured from bottle using the formulae.brew.sh API on 2025-01-23 at 07:15:04
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/o/openssl@3.rb
License: Apache-2.0
==> Dependencies
Required: ca-certificates ✔
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
/opt/homebrew/etc/openssl@3/certs
and run
/opt/homebrew/opt/openssl@3/bin/c_rehash
==> Analytics
install: 317,619 (30 days), 1,198,660 (90 days), 4,906,371 (365 days)
install-on-request: 39,374 (30 days), 166,937 (90 days), 638,675 (365 days)
build-error: 6,004 (30 days)
よし。
で、「.zshrc」の内容を確認して、以下があることを確認。
export LDFLAGS="-L/opt/homebrew/opt/openssl@3/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl@3/include"
export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@3/lib/pkgconfig"
pythonもインストールしなおすぞ。
pyenv uninstall 3.11.11
pyenv install 3.11.11
pyenv global 3.11.11
python --version
Python 3.11.11
よし。
では、pythonからopensslが見られるかどうか確認しよう。
python -c "import ssl; print(ssl.OPENSSL_VERSION)"
OpenSSL 3.4.0 22 Oct 2024
オッケーだね。
6)今回の障害のまとめ
ssl モジュールが必要だったのだが、pythonが認識できる状態になかった。
なので、もろもろ再インストールを行ったことで解決した。
では気を取り直して
7)環境構築再開
すでにつくった仮想環境を消す。
deactivate
rm -rf venv
環境を作る
python -m venv venv
source venv/bin/activate
flask入れる
pip install flask
よし、問題なし。
ここまで長かった!
3-4.routes.pyとrun.pyを作成
ひとまずAPIをさくっと作成。
backend/app/routes.py
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api/hello')
def hello():
return jsonify({'message': 'Hello from Flask!'})
backend/run.py
from app.routes import app
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
よしできた。
4.VSCodeで開く
おっと・・・。
まだVSCodeでファイル開いてなかった笑
なので、開く。
4-1.VSCodeで「project」フォルダを開く
1)問題発生!
開いてみたのだが、frontendのvueファイルでなんかエラーが出てる
Parsing error: No Babel config file detected
for /Users/mac-user/git/project/frontend/src/App.vue.
Either disable config file checking with requireConfigFile: false,
or configure Babel so that it can find the config files.eslint
え?なにこれ?
2)原因
これは、プロジェクトに Babel の設定ファイル(babel.config.js や .babelrc 等)が存在しないため
に起こっています。Vue CLI を使って新規プロジェクトを作成するときの選択内容によっては、Babel が設定されないまま生成されるケースがあります。
vue create .
この時に、「Default (Vue 3) or Default (Vue 2) 」を選ぶと、通常 Babel が含まれます。
うーーーん、まさかの作り間違え?
再度作成やってみる・・・。
が・・・解決しなかった・・・。
なにこれ?
3)本当の原因
原因は「フォルダの構造」と、プロジェクトを開いている「場所」。
「frontend」をVSCodeで開けば問題ない。
だけど、「project」フォルダを開いていることにより問題が起こる。
project/
│
├── frontend/ # Vue.jsアプリケーション
│ └── ...
うーん。
だけども望んでいるのは
「project」フォルダを開いた時も、「frontend」フォルダを開いた時も、
どちらでも正しく動くこと。
そのためにどうしたらいいのだろうか?
4)対応策
「マルチルート ワークスペース」を利用することで解決するらしい。
なるほど、試してみよう。
projectフォルダの直下に以下を作成する。
project.code-workspace
// project.code-workspace
{
"folders": [
{
"path": "frontend"
},
{
"path": "backend"
}
],
"settings": {
"eslint.workingDirectories": [
// frontend ディレクトリをルートに (Babel/ESLint) を実行
{
"directory": "frontend",
"changeProcessCWD": true
}
]
}
}
そして、VSCodeで「project.code-workspace」を開く。
すると・・・。
解決した!
5.実行テスト
では、frontとbackの動作確認テストだ。
5-1.フロントエンド実行
npm run serve
問題なく動作した。
5-2.バックエンド実行
source venv/bin/activate
python run.py
1)問題発生!
python run.py
* Serving Flask app 'app.routes'
* Debug mode: on
Address already in use
Port 5000 is in use by another program. Either identify and stop that program, or start the server with a different port.
On macOS, try disabling the 'AirPlay Receiver' service from System Preferences -> General -> AirDrop & Handoff.
うぉぉぉ。なんじゃこりゃ?
落ち着いてエラーをみると・・・。
2)原因
Mac だと AirPlay Receiver が当該ポート(5000)を使ってる
なるほど。
3)対策
じゃぁ、
「 Flaskを別のポートで起動」
で対応しよう。
backend/run.py
if __name__ == "__main__":
app.run(debug=True, port=5001)
こうやってポートを変更。
当然、vueの方もURLを変更するよ
const response = await axios.get('http://localhost:5001/api/hello');
4)再実行
python run.py
* Serving Flask app 'app.routes'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5001
* Running on http://192.168.13.38:5001
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 123-835-018
よし起動した。
5-3.実行確認
早速ブラウザでフロントにアクセス。
あれ?真っ白だな。
なんだこれ?
ブラウザのデベロッパーツールで確認してみると・・・。
localhost/:1 Access to XMLHttpRequest at 'http://localhost:5001/api/hello' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
おおう、CORSのエラーか・・・。
ならば、バックエンドに下記をインストール。
pip install flask-cors
backend/app/routes.pyもこんな感じに書き換える。
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route('/api/hello')
def hello():
return jsonify({'message': 'Hello from Flask!'})
気を取り直して再チャレンジ。
Hello from Flask!
よし。
(fin)