@koichi_sugi

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

pythonプログラムをexe化するときのファイルpathをどうすればいいか?

解決したいこと

csvファイルを分割するプログラムをpythonで作成し、想定通り動作できました。ただ、その後、pyinstallerでexe化もできたのですが、exeファイルを実行すると、思ったとおり、FileNotFoundError:になります。csvファイルをドラッグして実行するにはどうしたらよいか教えていただけないでしょうか?

発生している問題・エラー

FileNotFoundError: [Errno 2] No such file or directory: 'C:\Users\sugi\AppData\Local\Temp\_MEI123162\input.csv'

該当するソースコード

言語名 python
ソースコードを入力

import csv
import os

def split_csv(input_file):

 # プログラムファイルのディレクトリを取得
current_directory = os.path.dirname(os.path.abspath(__file__))

# 入力ファイルのパスを生成
input_file_path = os.path.join(current_directory, input_file)

# CSVファイルを読み込む
with open(input_file_path, 'r', encoding='utf-8') as file:
    reader = csv.reader(file)
    header = next(reader)  # ヘッダーを取得
    data = [row for row in reader]

# 2列目のデータごとに分割
grouped = {}
for row in data:
    key = row[1]  # 2列目のデータをキーとして使用
    if key not in grouped:
        grouped[key] = []
    grouped[key].append(row)

# 出力ディレクトリを作成
output_dir = os.path.join(current_directory, 'output')
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# データを分割してCSVファイルとして保存
for key, rows in grouped.items():
    output_file = os.path.join(output_dir, f"{key}.csv")
    with open(output_file, 'w', newline='', encoding='utf-8') as file:
        writer = csv.writer(file)
        writer.writerow(header)  # ヘッダーを書き込む
        writer.writerows(rows)
        print(f"分割されたファイル: {output_file}")

if name == "main":
# 入力ファイルのファイル名を指定して実行
input_file_name = 'input.csv'
split_csv(input_file_name)

自分で試したこと

csvファイルのpathをどうにかすればいいのではと思うのですが、知識不足で分かりません。

0 likes

2Answer

csvのファイルパスを引数で受け取るようにして、python内では絶対パスを意識しないようにするのはどうでしょうか。

hoge.py
import sys
if len(sys.argv) > 1:
    input_file_path = sys.argv[1]
    print(input_file_path)
    with open(input_file_path, 'r') as f:
        print(f.read())
else:
    print('引数が指定されていません')

csvの相対パス名やフルパス名を引数に指定します。

hoge C:\Users\user\Desktop\input.csv
1Like

Comments

  1. @koichi_sugi

    Questioner

    csvのファイル名をコマンドラインの引数に指定してうまく動作しました。
    ただexe化した時にうまく動作しません。
    chatGPTに聞いたら、「ユーザーはターミナルやコマンドプロンプトを介してプログラムを起動し、引数を直接指定します。しかし、ドラッグ&ドロップ操作では、ユーザーがファイルをプログラムのアイコンにドラッグしてドロップする形でファイルをプログラムに渡します。この場合、通常のコマンドライン引数が使用されないため、プログラムがそのままでは正しく動作しない可能性があります。」と回答されました。
    プログラムに間違ったところがあるのでしょうか?

    import csv
    import os
    import sys

    def split_csv(input_file):
    # プログラムファイルのディレクトリを取得
    current_directory = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(file)))

    # ドラッグ&ドロップされたファイルのパスを生成
    input_file_path = os.path.join(current_directory, input_file)
    
    # 入力ファイルの存在を確認
    if not os.path.exists(input_file_path):
        print(f'指定されたファイル "{input_file}" は存在しません')
        return
    
    # CSVファイルを読み込む
    with open(input_file_path, 'r', encoding='utf-8') as file:
        reader = csv.reader(file)
        try:
            header = next(reader)  # ヘッダーを取得
        except StopIteration:
            print("入力ファイルにヘッダー行がありません")
            return
        data = [row for row in reader]
    
    # 2列目のデータごとに分割
    grouped = {}
    for row in data:
        key = row[1]  # 2列目のデータをキーとして使用
        if key not in grouped:
            grouped[key] = []
        grouped[key].append(row)
    
    # 出力ディレクトリを作成
    output_dir = os.path.join(current_directory, 'output')
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # データを分割してCSVファイルとして保存
    for key, rows in grouped.items():
        output_file = os.path.join(output_dir, f"{key}.csv")
        with open(output_file, 'w', newline='', encoding='utf-8') as file:
            writer = csv.writer(file)
            writer.writerow(header)  # ヘッダーを書き込む
            writer.writerows(rows)
    print(f"分割が完了しました。出力ディレクトリ: {output_dir}")
    

    if name == "main":
    # コマンドライン引数から入力ファイルを取得
    if len(sys.argv) > 1:
    input_file_name = sys.argv[1]
    split_csv(input_file_name)
    else:
    print('引数が指定されていません')

'C:\Users\sugi\AppData\Local\Temp_MEI123162\input.csv'

PyInstallerがこの位置にpyファイルを書き込む事で引き起こされているのでは無いでしょうか。
引数に実行パスが含まれるので

import sys

current_directory = os.path.dirname(os.path.abspath(sys.argv[0]))

することで正しいパスを得られるとは思います。

ただ使い勝手を考慮するのならnak435が提案されている方法が賢明かと思われます。
引数方式であれば生成したexeファイルの上にcsvファイルをD&Dすることで済みますから。

1Like

Your answer might help someone💌