Python / Pyinstaller 转换:类型错误:join() 参数必须是 str、bytes 或 os.PathLike 对象,而不是“列表”

问题描述 投票:0回答:1

我的 python 脚本执行时效果很好。但是,我要求将其作为独立的 .exe 文件。 所以,我尝试使用 Pyinstaller 来转换它。我已经克服/解决了许多错误 - 但是,这个错误却困扰着我!

Traceback (most recent call last):
  File "Convert_TopStepX_Orders_to_Pinescript.py", line 133, in <module>
    modify_spreadsheet(os.path.join(script_dir, xlsx_file), output_file)
                       ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen ntpath>", line 139, in join
  File "<frozen genericpath>", line 188, in _check_arg_types
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'list'
[PYI-10584:ERROR] Failed to execute script 'Convert_TopStepX_Orders_to_Pinescript' due to unhandled exception!

如有任何帮助,我们将不胜感激!

上面提到的修改电子表格代码行上面有一个注释“# Call the function”

我怀疑这可能与此处回复中提出的解决方案有关: https://devsolus.com/2021/12/02/python-typeerror-join-argument-must-be-str-bytes-or-os-pathlike-object-not-list/?amp=1

不幸的是,我对 Python 的了解不够,无法理解如何将特定的解决方案应用于我的问题。

这是整个脚本:

import pandas as pd
import sys, os
from datetime import datetime
import glob
from shutil import rmtree
import re
import ntpath

def CLEANMEIFOLDERS():
    #Getting the current run _MEI path
    try:
        base_path = sys._MEIPASS

    #I don't know if this part is crucial or not since it only works if you don't use
    #--onefile in pyinstaller, which makes the use of this function unnecessary
    except Exception:
        base_path = os.path.abspath(".")

    #Extracting the updir of current run path to search for _MEI folders for the previous runs,
    #cave man style. Please update this part if you know a better way.
    base_path = base_path.split("\\")
    base_path.pop(-1)
    temp_path = ""
    for item in base_path:
        temp_path = temp_path + item + "\\"

    #Search the path for _MEI folders and delete them if they are not for the current run
    mei_folders = [f for f in glob.glob(temp_path + "**/", recursive=False)]
    for item in mei_folders:
        if item.find('_MEI') != -1 and item != sys._MEIPASS + "\\":
            rmtree(item)

# Get the script directory
script_dir = os.path.dirname(__file__)

# Get a list of all CSV files in the directory
csv_files = [f for f in os.listdir(script_dir) if f.endswith(".csv")]

# Loop over the CSV files
for csv_file in csv_files:
    # Extract the file name without the extension
    file_name = os.path.splitext(csv_file)[0]

    # Extract the text prior to "orders" from the file name
    if "orders" in file_name:
        new_file_name = file_name.split("orders")[0]
    else:
        new_file_name = file_name

    # Construct the output Excel file name
    xlsx_file = f"{new_file_name}.xlsx"

    # Read the CSV file into a pandas DataFrame
    df = pd.read_csv(os.path.join(script_dir, csv_file))

    # Save the DataFrame to an Excel file
    df.to_excel(os.path.join(script_dir, xlsx_file), index=False)

    # Delete the original CSV file
    #os.remove(os.path.join(script_dir, csv_file))

    print(f"Converted {csv_file} to {xlsx_file} and deleted the original CSV file")

# Create the output folder if it doesn't exist
output_folder = os.path.join(script_dir, "Trade Executions Scripts")
os.makedirs(output_folder, exist_ok=True)

def modify_spreadsheet(input_file, output_file):
    # Read the Excel file
    df = pd.read_excel(input_file)

    # Remove rows with "cancelled by system" or "cancelled by trader" in any cell
    df = df[~df.apply(lambda row: row.astype(str).str.contains('cancelled by system|cancelled by trader|Maximum position exceeded', case=False).any(), axis=1)]

    # Convert the date and time column to the desired format
    df.iloc[:, 9] = pd.to_datetime(df.iloc[:, 9]).apply(lambda x: f"{x.year}, {x.month}, {x.day}, {x.hour}, {x.minute}, {x.second}")

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.iloc[:, 15].apply(lambda x: 'color = i_close_col' if x == 'ClosePosition' else x)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.iloc[:, 15].apply(lambda x: 'color = i_stop_loss_col' if x == 'StopLoss' else x)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.iloc[:, 15].apply(lambda x: 'color = i_take_profit_col' if x == 'TakeProfit' else x)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.apply(lambda row: 'color = i_buy_col' if (row.iloc[6] == 'Bid' and row.iloc[14] == 'Opening' and row.iloc[15] == 'Trader') else row.iloc[15], axis=1)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.apply(lambda row: 'color = i_sell_col' if (row.iloc[6] == 'Ask' and row.iloc[14] == 'Opening' and row.iloc[15] == 'Trader') else row.iloc[15], axis=1)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.apply(lambda row: 'color = i_close_col' if (row.iloc[6] == 'Ask' and row.iloc[14] == 'Closing' and row.iloc[15] == 'Trader') else row.iloc[15], axis=1)

    # Replace the text in column 15 with pinescript colors\code
    df.iloc[:, 15] = df.apply(lambda row: 'color = i_close_col' if (row.iloc[6] == 'Bid' and row.iloc[14] == 'Closing' and row.iloc[15] == 'Trader') else row.iloc[15], axis=1)

    #-------------------

    # Replace the text in column 14 with pinescript code for arrows that relate to the color codes in the section above
    df.iloc[:, 14] = df.apply(lambda row: "char = '\u25B2'+'  '" if (row.iloc[15] == 'color = i_buy_col') else row.iloc[14], axis=1)

    # Replace the text in column 14 with pinescript code for arrows that relate to the color codes in the section above
    df.iloc[:, 14] = df.apply(lambda row: "char = '\u25BC'" if (row.iloc[15] == 'color = i_sell_col') else row.iloc[14], axis=1)

    # Replace the text in column 14 with pinescript code for arrows that relate to the color codes in the section above
    df.iloc[:, 14] = df.apply(lambda row: "char = '\u25B6'" if (row.iloc[15] == 'color = i_take_profit_col') else row.iloc[14], axis=1)

    # Replace the text in column 14 with pinescript code for arrows that relate to the color codes in the section above
    df.iloc[:, 14] = df.apply(lambda row: "char = '\u25C0'" if (row.iloc[15] == 'color = i_close_col' or row.iloc[15] == 'color = i_stop_loss_col') else row.iloc[14], axis=1)

    #-------------------

    # Remove unwanted columns: A, B, C, D, K, Q
    df = df.drop(df.columns[[0, 1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 16]], axis=1)

    # Save the updated spreadsheet without header\title row
    df.to_excel(output_file, index=False, header=False)

# Get the list of all xlsx files in the input directory
xlsx_file = [file for file in os.listdir(output_folder) if file.endswith(".xlsx")]
xlsx_files = [f for f in os.listdir(script_dir) if f.endswith(".xlsx")]

# Loop over the xlsx files and modify them
for xlsx_file in xlsx_files:
    input_file = os.path.join(script_dir, xlsx_file)
    output_file = os.path.join(output_folder, f"{os.path.splitext(xlsx_file)[0]}_modified.xlsx")
    modify_spreadsheet(input_file, output_file)
    print(f"Modified {xlsx_file} and saved to {output_file}")

# Call the function
modify_spreadsheet(os.path.join(script_dir, xlsx_file), output_file)

#------------------

# Get the current date
current_date = datetime.now().strftime("%Y-%m-%d")

# Get a list of all files in the folder that end with ".xlsx"
split_files = [f for f in os.listdir(output_folder) if f.endswith(".xlsx")]

# Loop over the split files
for split_file in split_files:
    # Load the Excel spreadsheet
    df = pd.read_excel(f"{output_folder}/{split_file}")

    # Determine the number of rows in the spreadsheet
    num_rows = len(df)

    # Determine the number of splits needed
    num_splits = (num_rows + 20) // 25

    # Loop over the splits
    for i in range(num_splits):
        # Determine the start and end row indices for this split
        start_row = i * 25
        end_row = min((i + 1) * 25 + 5, num_rows)

        # Extract the subset of rows for this split
        subset_df = df.iloc[start_row:end_row]

        # Save the subset to a new spreadsheet with "modified" at the end of the file name
        output_file = f"{output_folder}/{split_file[:-5]}_split_{str(i+1)}.xlsx"
        subset_df.to_excel(output_file, index=False)
        print(f"Split {split_file} and saved to {output_file}")

# Delete unwanted files
for file in os.listdir(output_folder):
    file_path = f"{output_folder}/{file}"
    if not file.endswith(".txt") and not "split" in file and os.path.exists(file_path):
        try:
            os.remove(file_path)
        except Exception as e:
            print(f"Error deleting file {file}: {str(e)}")

#-------------------

# Get a list of all files in the folder that start with "split"
split_files = [f for f in os.listdir(output_folder) if f.endswith(".xlsx")]

# Loop over the split files
for file in split_files:
    try:
        # Load the Excel spreadsheet
        data = pd.read_excel(f"{output_folder}/{file}", header=None)
        # Count the number of rows
        row_count = data.shape[0]

        # Write the result to a new notepad
        base_name = os.path.splitext(file)[0]
        output_file = f"{output_folder}/{re.sub(r'modified_split|modified', 'trades', base_name)}.txt"
        with open(output_file, 'w', encoding='utf-8') as f:
            # Add the color definitions to the top of the file
            f.write(f"//@version=5\n")
            f.write(f"indicator('My Executions', overlay=true)\n")  # Modified line
            f.write("i_buy_col = input.color(color.rgb(109, 223, 2, 0), 'Color for Buy Arrows')\n")
            f.write("i_close_col = input.color(color.rgb(255, 255, 255, 0), 'Color for Close Order Arrows')\n")
            f.write("i_sell_col = input.color(color.rgb(251, 255, 0, 0), 'Color for Sell Arrows')\n")
            f.write("i_stop_loss_col = input.color(color.rgb(186, 0, 211, 0), 'Color for Stop Loss Arrows')\n")
            f.write("i_take_profit_col = input.color(color.rgb(0, 110, 255, 0), 'Color for Take Profit Arrows')\n\n")

            for i in range(row_count):
                f.write(f"data{i} = float(na)\n")
            for i in range(len(data)):
                f.write(f"data{i} := timestamp({data.iloc[i, 1]}) >= time and timestamp({data.iloc[i, 1]}) < time_close ? {data.iloc[i, 2]} : data{i}\n")
            # Iterate over the rows in the spreadsheet
            for i in range(len(data)):
                # Write the text to the notepad
                f.write(f"plotchar(data{i}, {data.iloc[i, 3]}, {data.iloc[i, 4]}, force_overlay = true, location=location.absolute, size=size.tiny)\n")
            print(f"Created Text Files: {file}, added pine script and saved to {output_file}")
    except Exception as e:
        print(f"Error processing file {file}: {str(e)}")

#-------------------

# Delete unwanted files
for file in os.listdir(output_folder):
    file_path = os.path.join(output_folder, file)
    if not file.endswith(".txt") and os.path.exists(file_path):
        try:
            os.remove(file_path)
        except Exception as e:
            print(f"Error deleting file {file}: {str(e)}")

# Delete xlsx file
for file in os.listdir(script_dir):
    if file.endswith(".xlsx"):
        file_path = os.path.join(script_dir, file)
        if os.path.exists(file_path):
            try:
                os.remove(file_path)
            except Exception as e:
                print(f"Error deleting file {file}: {str(e)}")

input("Press Enter to continue...")
python pyinstaller
1个回答
0
投票

这段代码就是问题所在:

xlsx_file = [file for file in os.listdir(output_folder) if file.endswith(".xlsx")]
xlsx_files = [f for f in os.listdir(script_dir) if f.endswith(".xlsx")]

# Loop over the xlsx files and modify them
for xlsx_file in xlsx_files:
    input_file = os.path.join(script_dir, xlsx_file)
    output_file = os.path.join(output_folder, f"{os.path.splitext(xlsx_file)[0]}_modified.xlsx")
    modify_spreadsheet(input_file, output_file)
    print(f"Modified {xlsx_file} and saved to {output_file}")

# Call the function
modify_spreadsheet(os.path.join(script_dir, xlsx_file), output_file)

底部对

os.path.join()
的调用(在对modify_spreadsheet的调用内)将
xlsx_file
作为其第二个参数传递。 但是
xlsx_file
是一个列表,正如您在这段代码的顶部看到的那样。 您无法将列表传递给
os.path.join()
,因此会出现错误。

© www.soinside.com 2019 - 2024. All rights reserved.