・Excel→SQL作成時の境界条件を考える必要がある(前チェックの必須項目が怪しい)★ ・事前分析はもっと改善できるのではないだろうか?EXPLANと組み合わせるとか★ ・整合性モニターに推定進捗を表示しているが、そこから推定残り時間を算出・表示できる気がする。 ・クラッシュや強制終了で中断した整合性チェックプロセスを再開できるようにする必要がある(再開可能フラグ)--restart →整合性チェックが途中終了した場合はフラグファイルが残されるようにして、それがある場合は進捗情報から結果未確定(エラーの除く)を再実施する ?→疑問。現在は全てSQL実行した後にファイル出力しているような気がする。本当に単なる再開で大丈夫か?SQL実行結果をタスクの結果確認時に個別に残しておく必要があるのではないか? そうしないと終了時に結果出力ができないような気がする。 でも、そのせいで実行時間が長くなってしまうのは防ぎたい ・ランチャープロセスに強制終了機能を付与する(強制終了可能フラグ) ・整合性チェックモニターにAPIでの制御送信機能を付与する -RUNNING時を除いて実行可能な実行(RUN) ※ 現在はRUNNINGのときに工程パネルごとブロックされてしまうのでこれをボタン単位のブロックに変える -RUNNING, STALE時に実行可能な強制終了(ランチャープロセス経由での子プロセス遮断) -RUNNING時を除いて実行可能な再開(--restart付与しての実行)(再開が可能な状態かの確認を行う必要がある) -下記の無効処理を有効/無効にするignore_control.jsonの設定 ボタン位置について、 現在は(実行)(キャンセル) これからは(実行)(再開)(強制終了)(キャンセル) ※実行できないステータスのときはボタン自体が表示されない ボタンの色は以下 ・(実行)←デフォルト(変化なし) ・(再開)←緑と白文字 ・(強制終了)←赤と白文字 ※クリック後に確認がほしい「本当に実行中の工程を強制終了しますか?」 ・(キャンセル)←デフォルト(変化なし) ・□後続工程実行 また、実行中などの場合は変更できないようにグレーアウト ・□工程無効(チェックされた瞬間ではなく、ignore_control.jsonの状態や書き込み成功に準じてチェックしてほしい) また、実行中などの場合は変更できないようにグレーアウト また、ignore_control.jsonを見て無効である場合は工程色を灰色にしてほしい ※ タイミングの問題で先にRUNNINGしている場合は無効にできないため、失敗するようにしてほしい ・うっかり実行を避けるためにバッチ文頭に置くパイプラインチェックが欲しい(無効はignore_control.jsonから取得) {"t00":true, "t01":false, ...} ・2重実行を避けるためにパイプライン制御に2重実行防止を入れたい(工程ステータスにRUNNINGが1つ以上あり、1つ以上のデータ更新が10秒以内のときに既に実行中判定) (無効の場合は終了コード9、多重起動の場合は終了コード0x7F) ・終了コードを整理して危険域と安全域について整理。終了原因毎に0x10以上0x6F以下の結果コードを割り当てる ・Excelの各項目がどのようにSQLに反映されるのかを文章化してほしい。もしかしたら現在のコードが私の理解とは異なる可能性がある
ショートカットlinkimport argparse import socket import sys def get_local_ip(): """自身のローカルIPアドレスを取得する""" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('8.8.8.8', 80)) ip = s.getsockname()[0] except Exception: ip = '127.0.0.1' finally: s.close() return ip def main(): parser = argparse.ArgumentParser(description="ブラウザJSで疎通確認を行うリダイレクトHTMLを生成します。") parser.add_argument("--output-html", default="index.html", help="出力するHTMLファイル名") parser.add_argument("--protocol", default="http", help="プロトコル (デフォルト: http)") parser.add_argument("--port", default="9250", help="ポート番号 (デフォルト: 9250)") parser.add_argument("--urlpath", default="", help="URLのパス部分") parser.add_argument("--title", default="アプリケーションショートカット",help="タイトル") args = parser.parse_args() # IPの取得とURLの組み立て ip = get_local_ip() path = args.urlpath if args.urlpath.startswith("/") or not args.urlpath else "/{0}".format(args.urlpath) target_url = "{0}://{1}:{2}{3}".format(args.protocol, ip, args.port, args.urlpath) # HTMLテンプレート (JavaScriptで疎通確認) html_template = """<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{0}</title> <style> body {{ font-family: sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #f4f4f9; }} .card {{ background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); text-align: center; max-width: 400px; }} .spinner {{ border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 1s linear infinite; margin: 10px auto; }} @keyframes spin {{ 0% {{ transform: rotate(0deg); }} 100% {{ transform: rotate(360deg); }} }} .error {{ color: #e74c3c; display: none; }} a.urlLink {{ color: #3498db; text-decoration: none; font-weight: bold; }} a.btnTag {{ position: relative; display: inline-block; padding: 0.5rem 4rem; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-transition: all 0.3s; transition: all 0.3s; text-align: center; vertical-align: middle; text-decoration: none; letter-spacing: 0.1em; color: #212529; border-radius: 0.5rem; color: #fff; background-color: #eb6100; }} a.btnTag:hover {{ color: #fff; background: #f56500; }} </style> </head> <body> <div class="card"> <div id="status-ui"> <h4>{0}</h4> <p>疎通確認中...</p> <div class="spinner"></div> </div> <div id="error-ui" class="error"> <h4>{0}</h4> <p>接続に失敗しました...</p> <p><a class="urlLink" href="{1}">{1}</a></p> <a class="btnTag" href="#" onclick="location.reload()">再試行</a> </div> </div> <script> async function checkAndRedirect() {{ const url = "{1}"; const statusUi = document.getElementById('status-ui'); const errorUi = document.getElementById('error-ui'); console.log("[URL]:" + url); try {{ // mode: 'no-cors' を指定することで、CORS設定がないサーバーでもを確認可能 await fetch(url, {{ mode: 'no-cors', cache: 'no-cache' }}); // 疎通できればリダイレクト window.location.href = url; }} catch (e) {{ // 失敗した場合(サーバー未起動、ネットワークエラー等)は表示変更 statusUi.style.display = 'none'; errorUi.style.display = 'block'; }} }} // 実行開始 checkAndRedirect(); </script> </body> </html> """ with open(args.output_html, "w", encoding="utf-8-sig") as f: f.write(html_template.format(args.title, target_url)) if __name__ == "__main__": main()
簡単置換ツールimport argparse import json import logging from pathlib import Path import sys # ログの設定(コンソールにわかりやすく出力) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) def parse_arguments(): """コマンドライン引数をパースする""" parser = argparse.ArgumentParser( description="設定ファイルに従って、指定ディレクトリ内のファイル内容を置換します。" ) parser.add_argument("--input-directory", required=True, type=Path, help="入力ディレクトリのパス") parser.add_argument("--output-directory", required=True, type=Path, help="出力ディレクトリのパス") parser.add_argument("--file-name-pattern", required=True, help="対象ファイル名のパターン (例: *.txt)") parser.add_argument("--config-file", required=True, type=Path, help="置換ルールを定義したJSONファイルのパス") parser.add_argument("--encoding", default="utf-8", help="ファイルの文字エンコーディング (デフォルト: utf-8)") return parser.parse_args() def load_config(config_path: Path) -> dict: """JSON形式の設定ファイルから置換ルールを読み込む""" try: with open(config_path, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: logging.error("設定ファイルの読み込みに失敗しました: {0}\n詳細: {1}".format(config_path, e)) sys.exit(1) def process_file(input_path: Path, output_path: Path, replacements: dict, encoding: str): """単一ファイルの読み込み、置換、書き出しを行う""" try: # 出力先の親ディレクトリが存在しない場合は作成する output_path.parent.mkdir(parents=True, exist_ok=True) # ファイルの読み込み content = input_path.read_text(encoding=encoding) # 置換処理(辞書のキーを置換前、値を置換後とする) for old_word, new_word in replacements.items(): content = content.replace(old_word, new_word) # ファイルの書き出し output_path.write_text(content, encoding=encoding) logging.info("処理完了: {0} -> {1}".format(input_path.name, output_path)) except UnicodeDecodeError: logging.warning("エンコーディングエラー (スキップしました): {0} (指定エンコーディング: {1})".format(input_path, encoding)) except Exception as e: logging.error("ファイル処理中にエラーが発生しました: {0}\n詳細: {1}".format(input_path, e)) def main(): args = parse_arguments() # 1. 入力ディレクトリの存在確認 if not args.input_directory.is_dir(): logging.error("入力ディレクトリが存在しません: {0}".format(args.input_directory)) sys.exit(1) # 2. 設定ファイルの読み込み replacements = load_config(args.config_file) if not replacements: logging.warning("設定ファイルに置換ルールが定義されていません。") sys.exit(0) # 3. 出力ディレクトリの作成 args.output_directory.mkdir(parents=True, exist_ok=True) # 4. パターンに一致するファイルを再帰的に検索して処理 match_count = 0 for input_file in args.input_directory.rglob(args.file_name_pattern): if not input_file.is_file(): continue match_count += 1 relative_path = input_file.relative_to(args.input_directory) output_file = args.output_directory / relative_path process_file(input_file, output_file, replacements, args.encoding) if match_count == 0: logging.info("パターン '{0}' に一致するファイルは見つかりませんでした。".format(args.file_name_pattern)) else: logging.info("すべての処理が完了しました。") if __name__ == "__main__": main()
| 構成日時 | : | 2026-05-10 13:37:43 |
| 最古メッセージ日時 | : | 2026-05-04 16:56:20 |
| 最新メッセージ日時 | : | 2026-05-10 13:33:27 |
| メインスレッド数 | : | 3 |
| サブスレッド数 | : | 0 |
| 推定ページサイズ | : | 45.755KiB |