🎃

memo

に公開
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 5 モーダル</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

<!-- モーダルを開くボタン -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  モーダルを開く
</button>

<!-- モーダルのHTML -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">モーダルタイトル</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ここに内容を書きます。
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">閉じる</button>
        <button type="button" class="btn btn-primary">保存する</button>
      </div>
    </div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

function hasModeAbc(url) {
  try {
    const parsedUrl = new URL(url);
    // searchParamsからmodeの値を取得して判定
    return parsedUrl.searchParams.get('mode') === 'abc';
  } catch (error) {
    // URLのパースに失敗した場合はfalseを返す
    return false;
  }
}

// 使用例
console.log(hasModeAbc("https://example.com/?mode=abc"));                   // true
console.log(hasModeAbc("https://example.com/?foo=bar&mode=abc"));             // true
console.log(hasModeAbc("https://example.com/?mode=abc&foo=bar"));             // true
console.log(hasModeAbc("https://example.com/?mode=xyz&foo=bar"));             // false
console.log(hasModeAbc("https://example.com/?foo=bar&mode=abc&baz=qux"));      // true

その2

from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation

def copy_data_validation(ws, fromCell, toCell):
    """
    指定したセルのデータバリデーション(入力規則)をコピーする関数

    :param ws: 対象のワークシート
    :param fromCell: コピー元のセル(例: "A1")
    :param toCell: コピー先のセル(例: "B1")
    """
    # コピー元セルのデータバリデーションを取得
    for dv in ws.data_validations.dataValidation:
        if fromCell in dv.cells:
            original_dv = dv
            break
    else:
        raise ValueError(f"{fromCell} にデータバリデーションが見つかりません")

    # プルダウンリスト(リスト制約)の場合
    if original_dv.type == "list":
        new_dv = DataValidation(
            type="list",
            formula1=original_dv.formula1,  # リストの定義をコピー
            allowBlank=original_dv.allowBlank,
            showDropDown=original_dv.showDropDown,
            showErrorMessage=original_dv.showErrorMessage,
            showInputMessage=original_dv.showInputMessage,
            prompt=original_dv.prompt,
            promptTitle=original_dv.promptTitle,
            error=original_dv.error,
            errorTitle=original_dv.errorTitle,
            errorStyle=original_dv.errorStyle
        )

        # コピー先セルに適用
        new_dv.add(toCell)

        # ワークシートにデータバリデーションを追加
        ws.add_data_validation(new_dv)
    else:
        raise ValueError(f"{fromCell} のデータバリデーションはリスト型(プルダウン)ではありません")

# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active

# A1 から B1 に入力規則(プルダウン)をコピー
copy_data_validation(ws, "A1", "B1")

# 保存
wb.save("sample_copy.xlsx")
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation

# グローバル変数としてデータバリデーションを保持
original_dv = None  

def copy_data_validation(ws, fromCell, toCell):
    """
    指定したセルのデータバリデーション(入力規則)をコピーする関数
    1回目は `original_dv` を取得して保持し、2回目以降は再利用する。

    :param ws: 対象のワークシート
    :param fromCell: コピー元のセル(例: "A1")
    :param toCell: コピー先のセル(例: "B1")
    """
    global original_dv  # グローバル変数を使用

    # 1回目の実行時はコピー元のデータバリデーションを取得
    if original_dv is None:
        for dv in ws.data_validations.dataValidation:
            if fromCell in dv.cells:
                original_dv = dv
                break
        else:
            raise ValueError(f"{fromCell} にデータバリデーションが見つかりません")

    # 直接コピー先セルに追加
    original_dv.add(toCell)

    # 再度ワークシートにデータバリデーションを適用(必須)
    ws.add_data_validation(original_dv)

# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active

# 1回目のコピー(グローバル変数に保持)
copy_data_validation(ws, "A1", "B1")

# 2回目以降のコピー(`original_dv` を再利用)
copy_data_validation(ws, "A1", "C1")
copy_data_validation(ws, "A1", "D1")

# 保存
wb.save("sample_copy.xlsx")
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation

# グローバル変数としてデータバリデーションを保持
original_dv = None  

def copy_data_validation(ws, fromCell, toCell):
    """
    指定したセルのデータバリデーション(入力規則)をコピーする関数
    `fromCell` と `toCell` は `ws.cell(row=y, column=x)` で取得されたセルオブジェクト

    :param ws: 対象のワークシート
    :param fromCell: コピー元のセルオブジェクト(例: ws.cell(row=1, column=1))
    :param toCell: コピー先のセルオブジェクト(例: ws.cell(row=1, column=2))
    """
    global original_dv  # グローバル変数を使用

    # 1回目の実行時はコピー元のデータバリデーションを取得
    if original_dv is None:
        cell_ref = fromCell.coordinate  # A1 形式のセル参照
        for dv in ws.data_validations.dataValidation:
            if cell_ref in dv.cells:
                original_dv = dv
                break
        else:
            raise ValueError(f"{cell_ref} にデータバリデーションが見つかりません")

    # 直接コピー先セルに追加
    original_dv.add(toCell.coordinate)

    # 再度ワークシートにデータバリデーションを適用(必須)
    ws.add_data_validation(original_dv)

# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active

# A1 から B1 に入力規則をコピー
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=2))

# C1, D1 へもコピー
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=3))
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=4))

# 保存
wb.save("sample_copy.xlsx")

ExcelFitToPageSetter

from openpyxl import load_workbook

def set_fit_to_page(ws):
    """
    Excelの「次のページ数に合わせて印刷」を有効にし、
    縦のページ数の制限を解除する(空白にする)。
    
    :param ws: ワークシートオブジェクト
    """
    # 次のページ数に合わせて印刷を有効化
    ws.page_setup.fitToPage = True

    # 横を1ページに収める
    ws.page_setup.fitToWidth = 1  

    # 縦のページ数を「空白」にする(無制限)
    ws.page_setup.fitToHeight = None

# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active

# 設定を適用
set_fit_to_page(ws)

# 保存
wb.save("sample_modified.xlsx")
from openpyxl import load_workbook

# ワークブックを読み込む
wb = load_workbook("sample.xlsx")

# ワークシートを取得する
ws = wb["Sheet1"]

# ページ設定を行う
ws.page_setup.fitToWidth = 1  # 横方向に1ページに収める
ws.page_setup.fitToHeight = 0  # 縦方向のページ数を無制限にする

# ワークブックを保存する
wb.save("sample_modified.xlsx")
from openpyxl import load_workbook

def copy_sheet(file_path, source_sheet_name, target_sheet_name):
    # Excelブックを読み込み
    wb = load_workbook(file_path)

    # コピー元のシートを取得
    if source_sheet_name not in wb.sheetnames:
        raise ValueError(f"シート '{source_sheet_name}' が存在しません。")
    source_sheet = wb[source_sheet_name]

    # シートをコピー
    copied_sheet = wb.copy_worksheet(source_sheet)

    # コピーしたシートの名称を設定
    copied_sheet.title = target_sheet_name

    # ファイルを上書き保存
    wb.save(file_path)
    wb.close()

# 使用例
copy_sheet("sample.xlsx", "Sheet1", "Sheet1_Copy")

from openpyxl import load_workbook
from openpyxl.worksheet.worksheet import Worksheet

def copy_sheet_with_settings(file_path, source_sheet_name, target_sheet_name):
    # Excelブックを読み込み
    wb = load_workbook(file_path)

    # コピー元のシートを取得
    if source_sheet_name not in wb.sheetnames:
        raise ValueError(f"シート '{source_sheet_name}' が存在しません。")
    source_sheet = wb[source_sheet_name]

    # シートをコピー
    copied_sheet = wb.copy_worksheet(source_sheet)
    copied_sheet.title = target_sheet_name

    # 印刷範囲のコピー
    if source_sheet.print_area:
        copied_sheet.print_area = source_sheet.print_area

    # 印刷オプションのコピー(ヘッダー、フッター、グリッド線、拡大縮小など)
    copied_sheet.print_options.horizontalCentered = source_sheet.print_options.horizontalCentered
    copied_sheet.print_options.verticalCentered = source_sheet.print_options.verticalCentered
    copied_sheet.print_options.gridLines = source_sheet.print_options.gridLines
    copied_sheet.print_options.headings = source_sheet.print_options.headings

    # シートビュー(標準ビューや改ページプレビューの状態)をコピー
    if hasattr(source_sheet, 'views') and source_sheet.views:
        copied_sheet.views = source_sheet.views

    # ファイルを上書き保存
    wb.save(file_path)
    wb.close()

# 使用例
copy_sheet_with_settings("sample.xlsx", "Sheet1", "Sheet1_Copy")

from openpyxl import load_workbook

def select_all_sheets_and_set_first_active(file_path):
    # Excelブックを開く
    wb = load_workbook(file_path)

    # 全シートの選択を解除
    for ws in wb.worksheets:
        ws.sheet_view.tabSelected = False

    # すべてのシートを選択状態にする
    for ws in wb.worksheets:
        ws.sheet_view.tabSelected = True

    # 一番左のシートをアクティブにする
    wb.active = 0  # 最初のシートをアクティブに設定

    # ファイルを保存
    wb.save(file_path)
    wb.close()

# 使用例
select_all_sheets_and_set_first_active("sample.xlsx")


Excelの仕様

Excelでは「選択済みのシート は tabSelected=True のシートが 1つ以上ある状態」
ただし、「アクティブなシートは必ず1つだけ」 でなければならない
もし、すでに tabSelected=True のシートがあって、別のシートを tabSelected=True にすると どのシートがアクティブなのか不明確になる
openpyxlの内部動作

openpyxl は「アクティブなシートが必ず1つである」ことを期待している
tabSelected=True を複数のシートに設定するとき、一度 すべて False にしないと、どのシートがアクティブかの整合性が取れなくなる可能性がある
Excel のUIでは、 手動で「すべてのシートを選択」すると、自動的に1つのシートがアクティブになる 仕様になっているため、これを openpyxl でも再現するには、 一度すべて False にしてから True にする方が安全

            /*
                画面リロードから再表示完了までスピナーを表示するようにしたため
                途中でjavascriptエラーが発生時に、スピナーが表示されっぱなしになることを防ぎたい。
                ( 処理に時間がかかっているのか、エラーがあるのか判断できなくなるから )
                そのため、catchしてないjavascriptの例外を捕獲して
                スピナーを消す。
                その際、エラーの通知、および、詳細なデバッグ情報をconsole.error()をしておく
            */
            window.addEventListener('error', function (event) {
                let errorMessage = getErrorMessageOnGlobalError(event);

                let isAlert = true;
                /*
                    videoタグをカルーセルに入れてから、
                    カルーセルでページ切り替え中に、時々、
                    message : ResizeObserver loop completed with undelivered notifications.
                    のようなエラーメッセージで、ここに飛んでくる。原因不明である。

                    ただ、ここにエラーが飛んでくるだけで画面表示がおかしくなったりもしない
                    特に実害がないため、
                    ブラウザのデバッガーで見れるコンソールには出力しておくが、alert表示をしないことにした。
                */
                let specialError00100 = errorMessage.includes('ResizeObserver loop completed');
                if(specialError00100) {
                    isAlert = false;
                }

                console.error('エラーが発生しました:', errorMessage);

                if(isAlert) {
                    alert('エラーが発生しました');
                }
                
                // スピナーを消す
                hideSpinner();
            });




/**
 *  「window.addEventListener('error', function (event) {」
 *  グローバルにcatchしてないjavascript例外を捕獲した時のeventオブジェクトより
 *  詳細なデバッグ情報のあるerrorMessageを取得する。
 */
function getErrorMessageOnGlobalError(event) {
    let errorMessage = `message : ${event.message}  source : ${event.filename}:${event.lineno}:${event.colno}`;
    if (event.error) {
        if (event.error.stack) {
            errorMessage += `stacktrace : ${event.error.stack}`;
        }
    }
    return errorMessage;
}
import pandas as pd
import copy

# 検証用のDataFrame(コピー先の列は未定義)
df = pd.DataFrame({
    'col1': [[1, 2], [3, 4], [5, 6]]  # リストを含むケース
})

# 'col2' に 'col1' の完全コピーを作成(deep copy)
df['col2'] = df['col1'].apply(lambda x: copy.deepcopy(x))

# 'col1' を変更して 'col2' に影響があるかを確認
df.at[0, 'col1'].append(99)

# 結果の比較
df[['col1', 'col2']]
import pandas as pd
import copy

# ✅ 実装:完全コピー関数(col1, col2 に対し、None/空文字ならそれぞれ別のデフォルト値を適用)
def format_and_combine(row, col1_name, col2_name, default_value1, default_value2):
    val1 = str(row[col1_name]) if row[col1_name] not in [None, ''] else default_value1
    val2 = str(row[col2_name]) if row[col2_name] not in [None, ''] else default_value2
    return copy.deepcopy(f"{val1}_{val2}")

# ✅ 検証用データ(文字列、None、空文字、数値、ゼロ埋めなど多様なケースを網羅)
df = pd.DataFrame({
    'col1': [123456, None, '', '000001', 'abcdef', 0],
    'col2': ['654321', '', None, 999999, 0, '']
})

# ✅ col3 を新規作成(default値も個別に指定)
df['col3'] = df.apply(lambda row: format_and_combine(
    row, 'col1', 'col2', 'DEFAULT1', 'DEFAULT2'
), axis=1)


結果
     col1    col2               col3
0  123456  654321      123456_654321
1    None          DEFAULT1_DEFAULT2
2            None  DEFAULT1_DEFAULT2
3  000001  999999      000001_999999
4  abcdef       0           abcdef_0
5       0                 0_DEFAULT2
import pandas as pd
import copy

# ✅ 元の関数イメージ(deepcopy ありとなしを比較)
def format_and_combine_with_deepcopy(row, col1_name, col2_name, default_value1, default_value2):
    val1 = str(row[col1_name]) if row[col1_name] not in [None, ''] else default_value1
    val2 = str(row[col2_name]) if row[col2_name] not in [None, ''] else default_value2
    return copy.deepcopy(f"{val1}_{val2}")

def format_and_combine_without_deepcopy(row, col1_name, col2_name, default_value1, default_value2):
    val1 = str(row[col1_name]) if row[col1_name] not in [None, ''] else default_value1
    val2 = str(row[col2_name]) if row[col2_name] not in [None, ''] else default_value2
    return f"{val1}_{val2}"

# 検証用の単一行DataFrame(値・None・空文字含む)
df = pd.DataFrame({
    'col1': ['abc'],
    'col2': ['def']
})

# 両方の関数で結果を生成
result_with_deepcopy = df.apply(lambda row: format_and_combine_with_deepcopy(
    row, 'col1', 'col2', 'DEFAULT1', 'DEFAULT2'), axis=1)[0]

result_without_deepcopy = df.apply(lambda row: format_and_combine_without_deepcopy(
    row, 'col1', 'col2', 'DEFAULT1', 'DEFAULT2'), axis=1)[0]

# オブジェクトID(メモリアドレス)比較、内容比較
id_with = id(result_with_deepcopy)
id_without = id(result_without_deepcopy)
is_same_id = id_with == id_without
is_same_value = result_with_deepcopy == result_without_deepcopy

# val1/val2 の段階で deepcopy が不要かを確認するために、それぞれの id も取得
# val1/val2 自体も文字列として生成されており、それが deepcopy 不要かの確認
def get_val_ids(row):
    val1 = str(row['col1']) if row['col1'] not in [None, ''] else 'DEFAULT1'
    val2 = str(row['col2']) if row['col2'] not in [None, ''] else 'DEFAULT2'
    return id(val1), id(val2)

val1_id, val2_id = df.apply(get_val_ids, axis=1)[0]

# deepcopy 前の文字列の ID 取得(str(...) または default で代入された値)
val1_id, val2_id, id_with, id_without, is_same_id, is_same_value


結果
(139432584242336,
 139432571161536,
 139432493964928,
 139430791448448,
 False,
 True)
# ✅ 修正:values_match の判定ミスを修正
import pandas as pd

# ✅ 定数定義(default 値として使用)
DEFAULT_VALUE1 = 'XXXXXX'
DEFAULT_VALUE2 = 'XXXXXX'

# ✅ col1, col2 から col3 を作成(deepcopy 不要)
def format_and_combine(row, col1_name, col2_name, default_value1, default_value2):
    val1 = str(row[col1_name]) if row[col1_name] not in [None, ''] else default_value1
    val2 = str(row[col2_name]) if row[col2_name] not in [None, ''] else default_value2
    return f"{val1}_{val2}"

# ✅ 検証用データ(col3 は未定義)
df = pd.DataFrame({
    'col1': [123456, None, '', '000001', 'abcdef', 0],
    'col2': ['654321', '', None, 999999, 0, '']
})

# ✅ col3 を新規作成(未定義状態から)
df['col3'] = df.apply(lambda row: format_and_combine(
    row, 'col1', 'col2', DEFAULT_VALUE1, DEFAULT_VALUE2
), axis=1)

# ✅ 動作検証(値の確認)
expected_values = [
    "123456_654321",
    "XXXXXX_XXXXXX",
    "XXXXXX_XXXXXX",
    "000001_999999",
    "abcdef_0",
    "0_XXXXXX"
]

# 実際の値と期待値がすべて一致しているか確認
values_match = df['col3'].tolist() == expected_values

# col3 のオブジェクトID(新しい文字列オブジェクトが作られているか)
col3_ids = df['col3'].apply(id).tolist()

# col3 の要素ごとの deep copy 検証(各値が新しいオブジェクトになっているか)
deep_copy_check = all(col3_ids[i] != id(expected_values[i]) for i in range(len(expected_values)))

# ✅ 検証結果
values_match, deep_copy_check, df


結果
(True,
 True,
      col1    col2           col3
 0  123456  654321  123456_654321
 1    None          XXXXXX_XXXXXX
 2            None  XXXXXX_XXXXXX
 3  000001  999999  000001_999999
 4  abcdef       0       abcdef_0
 5       0               0_XXXXXX)
dataframeのto_excel()
をしたときに、
ValueError: Excel does not support datatimes with timezones. Please ensure that datetimes are timezone unaware before writing to Excel
のエラーになる

dataframeの行数、列数が大量にあるため、どの行のどの列か特定できない

しかし、エラーがでてるのは、おそらく、日時の項目ではないかと思われる

dataframeのto_excel()をしたのは、他の列の値について、行列がどうなってるかをデバッグのために知りたいからで

エラーになってる日時の値など、とりあえず、今、どうでもいいから、Excel出力したい

そこで、dataframeについて、上記のエラーが出る箇所

どこか、わからないが、いっきに、to_excel()ではエラーにならない。別の値に変換後のdataframeに対して

to_excel()がしたい



# セッションがリセットされたため再実行

import pandas as pd
import pytz

# ✅ 検証用の DataFrame:timezone-aware datetime を含む
df = pd.DataFrame({
    'id': [1, 2],
    'created_at': [
        pd.Timestamp('2023-01-01 12:00:00', tz='UTC'),
        pd.Timestamp('2023-01-02 13:30:00', tz='UTC')
    ],
    'name': ['Alice', 'Bob']
})

# ✅ 関数:timezone-aware な datetime を timezone-unaware に変換
def remove_timezone_in_df(df):
    for col in df.columns:
        if pd.api.types.is_datetime64_any_dtype(df[col]):
            if hasattr(df[col].dt, 'tz') and df[col].dt.tz is not None:
                df[col] = df[col].dt.tz_localize(None)
    return df

# ✅ タイムゾーンを除去した新しい DataFrame を作成
df_cleaned = remove_timezone_in_df(df.copy())

# ✅ Excel への保存を試行
output_path = "/mnt/data/cleaned_output.xlsx"
df_cleaned.to_excel(output_path, index=False)

# ✅ 出力結果の検証
output_path, df_cleaned.dtypes, df_cleaned.head()



結果
('/mnt/data/cleaned_output.xlsx',
 id                     int64
 created_at    datetime64[ns]
 name                  object
 dtype: object,
    id          created_at   name
 0   1 2023-01-01 12:00:00  Alice
 1   2 2023-01-02 13:30:00    Bob)
# セッションがリセットされたため再実行

import pandas as pd

# ✅ 検証用データフレーム("foo" は存在しない)
df = pd.DataFrame({
    'col1': ['bar', 'baz', 'qux']
})

# ✅ 一般論としての判定式:col1 が "foo" の行が 0 行かどうか
is_zero_foo = (df['col1'] == 'foo').sum() == 0

# ✅ 結果を表示
is_zero_foo, df

結果
(True,
   col1
 0  bar
 1  baz
 2  qux)
import pandas as pd
import numpy as np

# サンプルデータフレームの作成
data = {'A': range(1, 105), 'B': range(105, 209)}
df = pd.DataFrame(data)

# DataFrameBatchGenerator クラスの定義
class DataFrameBatchGenerator:
    def __init__(self, dataframe, batch_size=10):
        """
        コンストラクタ。

        :param dataframe: 分割対象のPandas DataFrame。
        :param batch_size: 各バッチの行数。デフォルトは10。
        """
        self.dataframe = dataframe
        self.batch_size = batch_size
        self.total_rows = len(dataframe)

    def __iter__(self):
        """
        イテレータを返すメソッド。
        """
        self.current_index = 0
        return self

    def __next__(self):
        """
        次のバッチを返すメソッド。

        :return: DataFrameのバッチ。
        :raises StopIteration: データがもう残っていない場合に発生。
        """
        if self.current_index >= self.total_rows:
            raise StopIteration

        start_idx = self.current_index
        end_idx = min(start_idx + self.batch_size, self.total_rows)
        batch = self.dataframe.iloc[start_idx:end_idx]
        self.current_index = end_idx
        return batch

# バッチサイズの定義
batch_size = 10

# DataFrameBatchGenerator のインスタンス化
batch_generator = DataFrameBatchGenerator(df, batch_size)

# バッチ処理とビュー・コピーの検証
for i, batch in enumerate(batch_generator):
    # メモリ共有の確認
    is_view = np.shares_memory(df.values, batch.values)
    
    # 結果の出力
    print(f"バッチ {i+1}: 行 {i*batch_size} から {i*batch_size + len(batch) - 1}")
    print(f"このバッチはビューか?: {'はい' if is_view else 'いいえ'}")
    print('-' * 50)


コードの説明:

サンプルデータフレームの作成:

2列('A'と'B')を持つデータフレームdfを作成しています。​

DataFrameBatchGenerator クラスの定義:

以前に提供したクラスと同一です。​

バッチ処理とビュー・コピーの検証:

DataFrameBatchGenerator を使用してデータフレームをバッチに分割します。​

各バッチに対して、np.shares_memory(df.values, batch.values) を用いて、元のデータフレームとバッチがメモリを共有しているかを確認します。​

各バッチの範囲と、ビューであるかどうかの結果をコンソールに出力します。​

注意点:

Pandasのバージョンによる挙動の違い:

Pandasのバージョンや設定によって、スライス時にビューが返されるかコピーが返されるかの挙動が異なる場合があります。​

特に、Pandas 1.5以降ではCopy-on-Write (CoW)モードが導入され、部分取得時にコピーが作成される挙動がデフォルトとなっています。​

np.shares_memory関数について:

この関数は、2つの配列がメモリを共有しているかを判定します。Trueが返された場合、2つの配列は同じメモリ領域を参照しており、変更が相互に影響します。Falseの場合、メモリを共有していないため、変更は相互に影響しません。​

このコードを実行することで、ご自身の環境でのDataFrameBatchGeneratorの挙動を確認し、各バッチがビューまたはコピーのどちらであるかを把握することができます。
 https://learn.microsoft.com/ja-jp/sql/connect/odbc/download-odbc-driver-for-sql-server

必要なパッケージのインストール:
sudo apt-get update
sudo apt-get install -y curl gnupg apt-transport-https
これにより、必要なツールとライブラリがインストールされます。

MicrosoftのGPGキーのインポート:
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

これにより、Microsoftのパッケージを信頼するためのGPGキーがシステムに追加されます。

Microsoftリポジトリの追加:
curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list

これにより、Microsoftのパッケージリポジトリがシステムのソースリストに追加されます。

パッケージリストの更新とODBCドライバのインストール:
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18

これにより、Microsoft ODBC Driver 18 for SQL Serverがインストールされます。

sudo apt update
sudo apt install unixodbc
これがlibodbc.so.2を提供する

dpkg -L unixodbc | grep libodbc.so.2
✅ MicrosoftのGPGキー・APT設定などをクリーンに削除する手順
🔹 1. MicrosoftのAPTリストを削除
bash
コピーする
編集する
sudo rm /etc/apt/sources.list.d/mssql-release.list
もし .list.save や .list.distUpgrade のようなファイルもあれば削除してOK:

bash
コピーする
編集する
sudo rm /etc/apt/sources.list.d/mssql-release.list.*
🔹 2. GPGキーの削除
キーをどこに保存したかにより、以下どちらか:

▸ /usr/share/keyrings/ に保存した場合:
bash
コピーする
編集する
sudo rm /usr/share/keyrings/microsoft-prod.gpg
▸ apt-key で追加した場合(古いやり方):
以下でキーのIDを確認:

bash
コピーする
編集する
apt-key list
Microsoft関連のキー(Microsoft (Release signing) <gpgsecurity@microsoft.com>)のIDを確認し、以下で削除:

bash
コピーする
編集する
sudo apt-key del <キーID>
例:

bash
コピーする
編集する
sudo apt-key del BC528686B50D79E339D3721CEB3E94ADBE1229CF
🔹 3. 不要になった .deb ファイルの削除(もし残っていれば)
bash
コピーする
編集する
rm ~/packages-microsoft-prod.deb 2>/dev/null
🔹 4. リポジトリキャッシュを更新
bash
コピーする
編集する
sudo apt update
これですべてクリーンな状態に戻せます。
必要があれば、Ubuntu標準のパッケージ(unixodbc など)もアンインストール案内できます。
続ける場合は「次の手順を教えて」と言ってください。
✅ 元に戻すために実行すべきコマンド(間違った構成の完全削除)
❶ MicrosoftのAPT設定を削除(おれが最初に言ったやつ)
bash
コピーする
編集する
sudo rm /etc/apt/sources.list.d/mssql-release.list
❷ GPGキーを削除(apt-keyで追加された場合)
bash
コピーする
編集する
sudo apt-key del EB3E94ADBE1229CF 2>/dev/null
※ 上記キーIDは Microsoft の公開鍵(もし違うIDの場合、apt-key list で確認してください)

❸ ダウンロードした .deb ファイルが残っていたら削除
bash
コピーする
編集する
rm -f packages-microsoft-prod.deb
❹ 間違ってインストールされたパッケージの削除
bash
コピーする
編集する
sudo apt remove --purge -y msodbcsql18 mssql-tools18
sudo apt autoremove -y
❺ bashrc 変更の取り消し(export PATH されていた場合)
bash
コピーする
編集する
sed -i '/\/opt\/mssql-tools18\/bin/d' ~/.bashrc
❻ APTキャッシュ更新
bash
コピーする
編集する
sudo apt update
sudo tee /etc/odbcinst.ini > /dev/null <<EOF
[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver=/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.so
UsageCount=1
EOF

sudo apt install --reinstall -y msodbcsql18

https://learn.microsoft.com/ja-jp/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver16&tabs=ubuntu18-install%2Calpine17-install%2Cdebian8-install%2Credhat7-13-install%2Crhel7-offline
公式

if ! [[ "20.04 22.04 24.04 24.10" == *"$(grep VERSION_ID /etc/os-release | cut -d '"' -f 2)"* ]];
then
    echo "Ubuntu $(grep VERSION_ID /etc/os-release | cut -d '"' -f 2) is not currently supported.";
    exit;
fi

# Download the package to configure the Microsoft repo
curl -sSL -O https://packages.microsoft.com/config/ubuntu/$(grep VERSION_ID /etc/os-release | cut -d '"' -f 2)/packages-microsoft-prod.deb
# Install the package
sudo dpkg -i packages-microsoft-prod.deb
# Delete the file
rm packages-microsoft-prod.deb

# Install the driver
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
# optional: for bcp and sqlcmd
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc
# optional: for unixODBC development headers
sudo apt-get install -y unixodbc-dev
sudo tee -a /etc/odbc.ini > /dev/null <<EOF

[sqlservertest]
Driver = ODBC Driver 18 for SQL Server
Server = 127.0.0.1,1433
UID = <ユーザ名>
PWD = <パスワード>
Encrypt = no
TrustServerCertificate = yes
EOF

isql -v "Driver=ODBC Driver 18 for SQL Server;Server=127.0.0.1,1433;UID=sa;PWD=yourpassword;Encrypt=no;TrustServerCertificate=yes"
import pyodbc

conn_str = (
    "DRIVER=ODBC Driver 18 for SQL Server;"
    "SERVER=127.0.0.1,1433;"
    "UID=admin;"
    "PWD=yourpassword;"
    "Encrypt=no;"
    "TrustServerCertificate=yes;"
)
try:
    conn = pyodbc.connect(conn_str, timeout=5)
    print("Success!")
except Exception as e:
    print("Failed:", e)


'ENGINE': 'sql_server.pyodbc',
'NAME': 'your_db_name',
'OPTIONS': {
    'dsn': 'sqlservertest',
    'autocommit': True,
}
# myproject/pyodbc_debug.py

import pyodbc

_original_connect = pyodbc.connect

def debug_connect(*args, **kwargs):
    print("\n=== pyodbc.connect called ===")
    print("args:", args)
    print("kwargs:", kwargs)
    print("================================\n")
    return _original_connect(*args, **kwargs)

pyodbc.connect = debug_connect

import subprocess

def get_windows_username():
    result = subprocess.run(
        ['cmd.exe', '/c', 'echo', '%USERNAME%'],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )
    return result.stdout.strip()
import pyodbc

try:
    conn = pyodbc.connect(
        "DRIVER={ODBC Driver 18 for SQL Server};"
        "SERVER=xxx.database.windows.net;"
        "DATABASE=xxx;"
        "UID=xxxx@aaaa.com;"
        "Authentication=ActiveDirectoryInteractive;"
        "Encrypt=yes;"
        "TrustServerCertificate=no;"
    )
except Exception as e:
    print("接続エラー:", e)
import msal
import struct

# Azure AD 設定
TENANT_ID = 'your-tenant-id'  # GUID形式(例: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
CLIENT_ID = 'your-client-id'  # Azure AD アプリ(Public Client アプリ)で取得
USERNAME = 'your-username@yourdomain.com'

# トークンを取得する関数
def get_access_token():
    app = msal.PublicClientApplication(
        CLIENT_ID,
        authority=f"https://login.microsoftonline.com/{TENANT_ID}"
    )
    scopes = ["https://database.windows.net//.default"]
    result = app.acquire_token_interactive(scopes=scopes, login_hint=USERNAME)
    if "access_token" in result:
        return result["access_token"]
    raise Exception(f"トークン取得失敗: {result.get('error_description')}")

# トークンをSQL Serverが受け取れる形式に変換(バイナリにして渡す)
access_token = get_access_token()
token_bytes = bytes(access_token, "utf-8")
token_struct = struct.pack(f"{len(token_bytes)}s", token_bytes)

# Django DATABASES 設定
DATABASES = {
    'default': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'your-db-name',
        'HOST': 'your-server-name.database.windows.net',
        'PORT': '1433',
        'USER': '',  # トークン認証では空文字でOK
        'PASSWORD': '',  # トークン認証では空文字でOK
        'OPTIONS': {
            'driver': 'ODBC Driver 18 for SQL Server',
            'extra_params': 'Authentication=ActiveDirectoryAccessToken',
            'attrs_before': {
                1256: token_struct  # 1256 = SQL_COPT_SS_ACCESS_TOKEN
            }
        }
    }
}
pip install msal django-pyodbc-azure
sudo apt install msodbcsql18
django==5.0.6
msal==1.25.0
pyodbc==5.1.0
django-mssql-backend==2.10.1

memo

双方向参照のコメントは間違いなので、

Djangoの設定やアプリ初期化前にDjangoモジュールを呼び出していることによる副作用
により、何か環境構築でミスってるのか。と思ってしまうような「ハマる」要素を誘うエラー内容でしたが
settings.pyの中で、自作のモジュールのimportをやめたら、その手のエラーがでなくなった経緯があります。

だったのが正確なところなので、
そのようなコメント記述に

import subprocess

def wslpath_w(linux_path: str) -> str:
    try:
        result = subprocess.run(['wslpath', '-w', linux_path], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        return result.stdout.strip()
    except subprocess.CalledProcessError as e:
        print(f"エラー: {e.stderr.strip()}")
        return ""

def main():
    linux_path = "/home/yourname/project"
    windows_path = wslpath_w(linux_path)
    if windows_path:
        print(f"Windowsパス: {windows_path}")
    else:
        print("パスの変換に失敗しました。")

if __name__ == "__main__":
    main()
import win32com.client
import os
import sys

def export_excel_to_pdf(excel_path, pdf_path):
    excel = None
    wb = None
    try:
        excel = win32com.client.Dispatch("Excel.Application")
        excel.Visible = False
        wb = excel.Workbooks.Open(excel_path)
        wb.ExportAsFixedFormat(0, pdf_path)
        print(f"✅ Exported to PDF: {pdf_path}")
    except Exception as e:
        print(f"❌ Error during export: {e}", file=sys.stderr)
        raise
    finally:
        if wb:
            wb.Close(False)
        if excel:
            excel.Quit()

def main():
    if len(sys.argv) != 3:
        print("Usage:")
        print("  python excel_to_pdf.py <input_excel_path> <output_pdf_path>")
        print("Example:")
        print(r"  python excel_to_pdf.py C:\path\to\file.xlsx C:\path\to\file.pdf")
        sys.exit(1)

    excel_file = sys.argv[1]
    pdf_file = sys.argv[2]

    if not os.path.exists(excel_file):
        print(f"❌ Excel file not found: {excel_file}", file=sys.stderr)
        sys.exit(1)

    export_excel_to_pdf(excel_file, pdf_file)

if __name__ == "__main__":
    main()


import subprocess

def run_excel_to_pdf_on_windows(excel_path, pdf_path):
    windows_python = "/mnt/c/Users/yourname/AppData/Local/Programs/Python/Python311/python.exe"
    script_path = "/mnt/c/scripts/excel_to_pdf.py"

    result = subprocess.run(
        [windows_python, script_path, excel_path, pdf_path],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )

    if result.returncode != 0:
        print("❌ エラー発生:")
        print(result.stderr)
    else:
        print("✅ 正常に完了:")
        print(result.stdout)


param (
    [string]$excelPath,
    [string]$pdfPath
)

$excel = $null
$workbook = $null

try {
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $false
    $workbook = $excel.Workbooks.Open($excelPath)
    $workbook.ExportAsFixedFormat(0, $pdfPath)
    Write-Output "Export successful: $pdfPath"
    exit 0
}
catch {
    Write-Error "Error: $_"
    exit 1
}
finally {
    if ($workbook) { $workbook.Close($false) }
    if ($excel)    { $excel.Quit() }
}


***********************************

import subprocess

def run_excel_to_pdf_via_powershell(excel_path, pdf_path, ps1_path):
    result = subprocess.run(
        [
            "powershell.exe",
            "-ExecutionPolicy", "Bypass",
            "-File", ps1_path,
            "-excelPath", excel_path,
            "-pdfPath", pdf_path
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )

    if result.returncode == 1:
        print("❌ PowerShell script failed.")
        print("STDOUT:", result.stdout.strip())
        print("STDERR:", result.stderr.strip())



openpyxl==3.1.5
Pillow>=7.0.0
'encoding': 'cp932'  # ← ここがポイント
'encoding': 'utf-8'  # ← これがWSL2用
function setTriggerUI(form, value) {
  // 既存の hidden input(name="triggerUI")を削除
  const existing = form.querySelector('input[name="triggerUI"]');
  if (existing) {
    existing.remove();
  }

  // 新しく hidden input を作成して追加
  const input = document.createElement('input');
  input.type = 'hidden';
  input.name = 'triggerUI';
  input.value = value;

  form.appendChild(input);
}

https://chatgpt.com/share/685d579b-260c-8005-8d95-d4cda0bb2472

https://chatgpt.com/share/685d576b-01b8-8005-8961-64886d64e9f0

#######################

https://ykuwai.notion.site/MCP-1f26372e8f4a8061a4a6c5b55887af36

$ cat ./.gemini/settings.json
{
    // すでに他の設定があれば残したまま追記
    "mcpServers": {
        "filesystem": {
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                "/udemy/mcp_koza/fs_dir",
                "/udemy/mcp_koza/fs_dir2",
                "/udemy/mcp_koza/restaurant"
            ]
        },
        "desktop-commander": {
            "command": "npx",
            "args": [
                "-y",
                "@wonderwhy-er/desktop-commander"
            ]
            /* 必要なら環境変数も追加
      ,"env": {
        "SOME_TOKEN": "xxxxx"
      }
      */
        },
        "context7": {
            "command": "npx",
            "args": [
                "-y",
                "@upstash/context7-mcp"
            ]
        }
    }
}

#######################

1 . 前提チェック
コマンド 出れば OK 補足
lsb_release ‑rs 20.04 / 22.04 / 24.04 それ以外は同じ手順で可だが Package 名が変わる可能性
sudo add-apt-repository universe 成功 openjdk‑21‑jdk を取るのに Universe が要る
grep ^deb /etc/apt/sources.list 通常表示 Proxy 環境なら Acquire::http::Proxy の設定を先に

2 . GPG 鍵を配置(apt-secure 新方式)
bash
コピーする
編集する
sudo mkdir -p /usr/share/keyrings

公開鍵をダウンロード → .gpg 形式に変換して格納

curl -fsSL https://dbeaver.io/debs/dbeaver.gpg.key
| sudo gpg --dearmor -o /usr/share/keyrings/dbeaver.gpg
鍵の指紋を必ず確認

bash
コピーする
編集する
gpg --show-keys --with-fingerprint /usr/share/keyrings/dbeaver.gpg
| grep -A1 pub
D3 3A 1B D7 25 ED 04 7D … が表示されれば正しい鍵です
Kali Linux Forum

3 . リポジトリを追加
bash
コピーする
編集する
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/dbeaver.gpg]
https://dbeaver.io/debs/dbeaver-ce/ /"
| sudo tee /etc/apt/sources.list.d/dbeaver.list
末尾の スラッシュ / を忘れない(署名付きリポジトリと apt のバグ回避)。

この InRelease は 2025‑07‑06 に更新され、最新版 25.1.2 を含みます。
dbeaver.io

4 . パッケージ更新 & インストール
bash
コピーする
編集する
sudo apt update

Java は同梱だが、フォントの不具合を防ぐため JDK 21 を入れておく

sudo apt install openjdk-21-jdk dbeaver-ce
openjdk‑21‑jdk は 20.04/22.04/24.04 いずれも Universe に正式収録済みです。
Ask Ubuntu

DBeaver 23.0 以降は OpenJDK 21 を同梱 していますが、
システム Java があるとフォントレンダリングやクリップボード連携が安定します。
dbeaver.io

5 . 動作確認
bash
コピーする
編集する

いったんシェルを再読み込み

dbeaver &
DBeaver → Help › About で 25.1.2 と表示されればインストール完了です。
dbeaver.io

さらに SQL コンソールで

sql
コピーする
編集する
SELECT sqlite_version();
が返れば、JDBC ドライバも自動ダウンロードできるネットワーク設定になっています。

よくあるトラブルと対処
症状 原因 解決
NO_PUBKEY D33A1BD725ED047D 鍵を .gpg 形式で置いていない 2 . の gpg --dearmor をやり直す
ドライバが落ちない Proxy / TLS ミス DBeaver 上の Window › Preferences › General › Network Connections を Direct か正しい Proxy に
起動直後にクラッシュ 古い設定が残存 ~/.local/share/DBeaverData/workspace6 を一時退避して起動

まとめ
公開鍵を /usr/share/keyrings/ に .gpg 形式で置く

deb [signed‑by=…] の新方式行を追加

sudo apt update && sudo apt install dbeaver-ce だけで最新版 25.1.2 が入る

以後は sudo apt upgrade で毎月のリリースを追従可能

以上、公式リポジトリと公開鍵を直接検証した 100 % 現行手順です。

grep -R "dbeaver.io/debs" /etc/apt/sources.list.d 2>/dev/null
# ❶ まだリポジトリ鍵+dbeaver.list を作っていなければ実行
# (すでに追加済みならこの 3 行はスキップ)
curl -fsSL https://dbeaver.io/debs/dbeaver.gpg.key \
 | sudo gpg --dearmor -o /usr/share/keyrings/dbeaver.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/dbeaver.gpg] \
 https://dbeaver.io/debs/dbeaver-ce/ /" \
 | sudo tee /etc/apt/sources.list.d/dbeaver.list

# ❷ インデックス更新
sudo apt update

# ❸ OpenJDK 21 と DBeaver 本体を一気に入れる
sudo apt install -y openjdk-21-jdk dbeaver-ce

sudo apt install openjdk-21-jdk # 先に Java だけ
sudo apt install dbeaver-ce # 後から DBeaver

// ── 親側 ──
const win = window.open('/child.html', 'myPopup'); // 名前再利用を避けたければ '' など

// ── 子側 (child.html) ──
document.addEventListener('DOMContentLoaded', () => {
  const hasParent = !!window.opener && !window.opener.closed;
  if (hasParent) {
    // リロード後も維持できるよう sessionStorage にフラグ
    sessionStorage.setItem('openedByParent', '1');
  }
});

// 以降は単に:
const openedByParent = sessionStorage.getItem('openedByParent') === '1';

★★★★★★★★★★★★★★★★★★★
★★★★★★★★★★★★★★★★★★★

# views.py
import uuid
from django.http import StreamingHttpResponse, FileResponse

def download_view(request):
    token = request.POST.get("dl_token")   # フォームから受け取る
    file_iter = my_slow_generator()        # 時間のかかるストリーム
    resp = StreamingHttpResponse(file_iter, content_type="application/zip")
    resp["Content-Disposition"] = 'attachment; filename="bigdata.zip"'

    # ★ トークンと同じ名前の Cookie を set
    #    header がブラウザに届いた瞬間 JS から読める
    resp.set_cookie(token, "1", max_age=600, httponly=False, secure=True)
    return resp

<script src="https://cdnjs.cloudflare.com/ajax/libs/uuid/8.2.0/uuid.min.js"
</script>

<form id="dl-form" action="/download/" method="post">
  {% csrf_token %}
  <input type="hidden" name="dl_token" id="dl_token">
  <button type="submit">ダウンロード</button>
</form>

<div id="spinner" hidden>Loading...</div>

<script>
document.getElementById("dl-form").addEventListener("submit", e => {
  // 1. ランダムトークンを発行
  const token = crypto.randomUUID();
  document.getElementById("dl_token").value = token;

  // 2. スピナーを表示
  document.getElementById("spinner").hidden = false;

  // 3. Cookie 到着をポーリングして検知
  const timer = setInterval(() => {
    if (document.cookie.includes(`${token}=1`)) {
      clearInterval(timer);
      // 後片付け
      document.cookie = `${token}=; Max-Age=0; path=/`;
      document.getElementById("spinner").hidden = true;
    }
  }, 300);            // 300 ms ごとに確認
});
</script>

Integrytyに仕込む値の取得方法
https://www.srihash.org/

<a href="downloadHoge" id="downloadLink">hogeをダウンロード</a>
<div id="spinner" style="display: none;">スピナー表示中...</div>

<script>
document.getElementById("downloadLink").addEventListener("click", function(event) {
  event.preventDefault(); // 一旦止める

  // スピナー表示
  document.getElementById("spinner").style.display = "block";

  // 少し遅らせてからダウンロード開始(スピナーが描画される時間確保)
  setTimeout(() => {
    const a = document.createElement("a");
    a.href = this.href;
    a.style.display = "none";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);

    // スピナーは自動では消えない(ダウンロード完了イベントがないため)
    // 必要なら手動で5秒後などに非表示化してもOK
    // setTimeout(() => {
    //   document.getElementById("spinner").style.display = "none";
    // }, 5000);
  }, 100); // 少しだけ遅延
});
</script>

*********************
オンライン端末(インターネットにつながる端末)で、
pip download -r requirements.txt -d wheels/

別にvenvに入らなくても、どこでも、
どのフォルダでも、pipコマンドさえ使える場所で、
requirements.txtがあれば実行可能。

この時に、オンライン端末でこのコマンドを打ち込むフォルダで
python3 -V( windows なら、python -V か)を打ち込んだときに
表示されるバージョンと、

オフライン側の、それとバージョンが一致しておればよい
pythonの実態のパスまでが同じである必要はない
*********************

オフライン端末側で、
python -m venv .venv
.venv\Scripts\activate (windowsの直の場合)
> ちなみに、
> Git bashなら source .venv\Scripts\activate 
> WSL2なら source .venv\bin\activate
にて、仮想環境にactivateした後、
pip install --no-index --find-links=.\wheels -r requirements.txt
( Git bash、WSL2の場合は、--find-links=./wheels )

--no-indexは、PyPIからのダウンロードをしないという意味

*********************

Windows 11 端末同士であれば、細かなwindowsのバージョン違うならOK
Python本体のインストール場所が違っていてもOK

cursorエディタのmcpの例

.cursor/mcp.json

{
    "mcpServers": {
      "context7": {
        "command": "npx",
        "args": [
          "-y",
          "@upstash/context7-mcp"
        ]
      },
      "github": {
        "command": "npx",
        "args": [
          "-y",
          "@modelcontextprotocol/server-github"
        ],
        "env": {
          "GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_XXXXXXX"
        }
      },
      "playwright": {
        "command": "npx",
        "args": [
          "@playwright/mcp@latest"
        ]
      }
    }
  }
  

dism /Online /Add-Capability /CapabilityName:Language.Basic~~~ja-JP~0.0.1.0

Set-WinDefaultInputMethodOverride -InputTip "0411:00000411"

windows環境では、
powershell 7以降の場合は、
echo $PROFILE
で表示されるパスのスクリプトに、( なければ、つくってでも )
mise activate pwsh | Out-String | Invoke-Expression
を追加する

上記は、powershell 5.1では、LocationChangedACtionが見つかりません
というエラーがでる。
powershell 5.1では、miseのactivated: yesが非対応であるため

shims_on_path: yes
にするしかない
その場合は、
powershellで、
echo $env:LOCALAPPDATA\mise\shims
した結果、表示されたパスを、
環境変数PATH に、GUIで追加したら、
恒久的に、次のpowershellのセッション以降 powershellでも、git bashでも、 mise doctorしたら、
shims_on_path: yes
になる。
shims_on_path: yes
は、ちょっと、切り替わりが遅いだけ(一般に数ミリ秒程度)で、activated: yes
と同じ使い方ができるものとのこと

aaaaa

echo 'mise activate pwsh | Out-String | Invoke-Expression' >> $HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

# Windows (Git Bash):
python  -m pip wheel odfpy==1.4.1 -w wheels
# WSL2:
python3 -m pip wheel odfpy==1.4.1 -w wheels
python3 -m pip wheel odfpy==1.4.1 -w wheels

<追記>

miseが絡んだ環境をいくつか切り替えてる時
pip installでキャッシュ関連のエラーに遭遇することがある

その場合は、

https://zenn.dev/tazzae999jp/articles/ed16c0ec8bc171

を参考にしてください!!

winget install Microsoft.WinDbg

WinDbgX -c ".symfix; .sympath+ %CD%\bin; .srcpath %CD%; .lines 1; .loadby sos clr; !bpmd unitTestCSharp.exe Program::Main; g" ".\bin\unitTestCSharp.exe"

build_net48.bat

@echo off
REM .NET 4.5~4.8はCLR 4.0(v4.0.30319)のin-place更新なので csc.exe は v4.0.30319 配下のまま

setlocal
set "FW=%WINDIR%\Microsoft.NET\Framework64\v4.0.30319"
set "CSC=%FW%\csc.exe"

if not exist "%CSC%" (echo [ERROR] csc.exe not found: %CSC% & exit /b 1)
if not exist ".\bin" mkdir ".\bin"

REM 参照は Dev Pack ではなく、ランタイム側の System*.dll を直接使う
"%CSC%" /nologo /debug:full /optimize- /target:exe /out:bin\unitTestCSharp.exe ^
 /r:"%FW%\System.dll" /r:"%FW%\System.Core.dll" ^
 src\cs\common.cs src\cs\unitTestCSharp.cs

if errorlevel 1 (echo [BUILD FAILED] & exit /b 1)

echo [BUILD OK] bin\unitTestCSharp.exe と PDB を作成
echo WinDbg 起動例: WinDbgX "%CD%\bin\unitTestCSharp.exe"
endlocal

winget uninstall --id Microsoft.WinDbg -e

winget uninstall --id Microsoft.WinDbg -e --source winget

winget list WinDbg

if not exist bin mkdir bin & "%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /nologo /debug:full /optimize- /target:exe /out:bin\unitTestCSharp.exe /pdb:bin\unitTestCSharp.pdb /r:"%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\System.dll" /r:"%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\System.Core.dll" src\cs\common.cs src\cs\unitTestCSharp.cs

https://github.com/dnSpyEx/dnSpy/releases

@echo off
REM build_net48_dbg.bat
REM 4.5~4.8 は CLR 4.0(v4.0.30319)へ“in-place更新”。よって csc.exe は v4.0.30319 配下。

REM ★ bin フォルダは「ある前提」。作成しない。
set "FW=%WINDIR%\Microsoft.NET\Framework64\v4.0.30319"
set "OUT=bin\unitTestCSharp.exe"
set "PDB=bin\unitTestCSharp.pdb"
set "RSP=%CD%\csc_args.rsp"

REM ── csc のレスポンスファイルを作る(行継続や ^ を使わず安全)
> "%RSP%"  echo /nologo
>>"%RSP%" echo /debug:full
>>"%RSP%" echo /optimize-
>>"%RSP%" echo /target:exe
>>"%RSP%" echo /out:%OUT%
>>"%RSP%" echo /pdb:%PDB%
>>"%RSP%" echo /langversion:latest
>>"%RSP%" echo /define:TRACE;DEBUG
>>"%RSP%" echo /nostdlib+
>>"%RSP%" echo /r:"%FW%\mscorlib.dll"
>>"%RSP%" echo /r:"%FW%\System.dll"
>>"%RSP%" echo /r:"%FW%\System.Core.dll"
>>"%RSP%" echo /r:"%FW%\Microsoft.CSharp.dll"

REM ── コンパイル(src\cs\common.cs と src\cs\unitTestCSharp.cs のみ)
"%FW%\csc.exe" @"%RSP%" src\cs\common.cs src\cs\unitTestCSharp.cs
if errorlevel 1 (
  echo [BUILD FAILED]
  exit /b 1
)

echo [BUILD OK] %OUT% と PDB を作成
echo WinDbg 例: WinDbgX "%CD%\%OUT%"

.NET Framework 4.8.09032
は、
C# 5まで、利用可であります

%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe

Discussion