My goal:
- drop a list of files.
- Read files and extract columns.
- Dynamically generate dropdown componenets so the user can select the source and target columns.
- I need to return (globally) all the selections, so I can use them with process_files() function.
I think (3) it should be solved using gr.State([ ])
but I am not sure how to update it.
here is my code:
Function to process files
import gradio as gr
import pandas as pd
def process_files(files, selections):
results = []
for file, selection in zip(files, selections):
file_name = file.name
source_col, target_col, source_lang, target_lang = selection
try:
if file_name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file_name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue # Skip unsupported files
# Extract selected columns
extracted_data = df[[source_col, target_col]]
results.append(
f"β
Processed {file_name} ({source_lang} β {target_lang})")
except Exception as e:
results.append(f"Error processing {file_name}: {str(e)}")
return "\n".join(results)
Gradio Interface
with gr.Blocks() as demo:
gr.Markdown("## Upload Multiple Files and Select Columns")
file_input = gr.File(file_types=[
".csv", ".xlsx"], label="Drop your files here", interactive=True, file_count="multiple")
all_selections = gr.State([])
@gr.render(inputs=[file_input], triggers=[file_input.change])
def generate_column_selectors(files):
if not files:
return "## No Files Uploaded", [] # Reset selections
with gr.Column():
for file in files:
try:
if file.name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file.name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue
with gr.Row():
gr.Markdown(f"**{file.name}**") # Display filename
source_col = gr.Dropdown(
df.columns.tolist(), label="Source Column", interactive=True)
target_col = gr.Dropdown(
df.columns.tolist(), label="Target Column", interactive=True)
source_lang = gr.Textbox(
label="Source Language", placeholder="e.g., English", interactive=True)
target_lang = gr.Textbox(
label="Target Language", placeholder="e.g., French", interactive=True)
all_selections.append(
(source_col, target_col, source_lang, target_lang)) # this does not work.
except Exception as e:
gr.Markdown(f"Error processing {file.name}: {str(e)}")
submit_button = gr.Button("Submit & Process", interactive=True)
output_text = gr.Markdown()
submit_button.click(process_files, inputs=[
file_input, all_selections], outputs=[output_text])
demo.launch()
1 Like
import gradio as gr
import pandas as pd
def process_files(files, selections):
results = []
for file, selection in zip(files, selections):
file_name = file.name
source_col, target_col, source_lang, target_lang = selection
try:
if file_name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file_name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue # Skip unsupported files
# Extract selected columns
extracted_data = df[[source_col, target_col]]
results.append(
f"β
Processed {file_name} ({source_lang} β {target_lang})")
except Exception as e:
results.append(f"Error processing {file_name}: {str(e)}")
return "\n".join(results)
with gr.Blocks() as demo:
gr.Markdown("## Upload Multiple Files and Select Columns")
file_input = gr.File(file_types=[".csv", ".xlsx"], label="Drop your files here", interactive=True, file_count="multiple")
all_selections = gr.State([])
@gr.render(inputs=[file_input], triggers=[file_input.change])
def generate_column_selectors(files):
if not files:
return "## No Files Uploaded", [] # Reset selections
selections = []
with gr.Column():
for file in files:
try:
if file.name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file.name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue
with gr.Row():
gr.Markdown(f"**{file.name}**") # Display filename
source_col = gr.Dropdown(df.columns.tolist(), label="Source Column", interactive=True)
target_col = gr.Dropdown(df.columns.tolist(), label="Target Column", interactive=True)
source_lang = gr.Textbox(label="Source Language", placeholder="e.g., English", interactive=True)
target_lang = gr.Textbox(label="Target Language", placeholder="e.g., French", interactive=True)
selections.append((source_col, target_col, source_lang, target_lang))
except Exception as e:
gr.Markdown(f"Error processing {file.name}: {str(e)}")
# Update the global state with the new selections
all_selections.value = selections
submit_button = gr.Button("Submit & Process", interactive=True)
output_text = gr.Markdown()
submit_button.click(process_files, inputs=[file_input, all_selections], outputs=[output_text])
demo.launch()
1 Like
@Alanturner2 Did you test it. It does not work. ChatGPT proposes this solution but it is not workable. It looks like that the elements in the gr.state are not pickable!!
File β/usr/lib/python3.10/copy.pyβ, line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File β/usr/lib/python3.10/copy.pyβ, line 161, in deepcopy
rv = reductor(4)
TypeError: cannot pickle β_thread.lockβ object
1 Like
like this? Itβs not perfect yet.
with gr.Column():
for file in files:
try:
if file.name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file.name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue
with gr.Row():
gr.Markdown(f"**{file.name}**") # Display filename
source_col = gr.Dropdown(
df.columns.tolist(), label="Source Column", interactive=True)
target_col = gr.Dropdown(
df.columns.tolist(), label="Target Column", interactive=True)
source_lang = gr.Textbox(
label="Source Language", placeholder="e.g., English", interactive=True)
target_lang = gr.Textbox(
label="Target Language", placeholder="e.g., French", interactive=True)
def append_sel(source_col, target_col, source_lang, target_lang, selections):
selections.append((source_col, target_col, source_lang, target_lang))
return selections
gr.on(triggers=[source_col.change, target_col.change, source_lang.change, target_lang.change],
fn=append_sel, inputs=[source_col, target_col, source_lang, target_lang, all_selections], outputs=[all_selections])
thanks @John6666. it still not perfect as gr.on() is trigeered on the first change of any element. if I insert just one Character in source_lang, it will trigger once and done.
1 Like
Finally! It is working! I still not fully understand the utility of gr.State() if it does not work in such scenario.
import gradio as gr
import pandas as pd
with gr.Blocks() as demo:
gr.Markdown("## Upload Multiple Files and Select Columns")
file_input = gr.File(file_types=[
".csv", ".xlsx"], label="Drop your files here", interactive=True, file_count="multiple")
@gr.render(inputs=[file_input], triggers=[file_input.change])
def generate_column_selectors(files):
selections = []
with gr.Column():
for file in files:
try:
if file.name.endswith(".csv"):
df = pd.read_csv(file.name)
elif file.name.endswith(".xlsx"):
df = pd.read_excel(file.name, engine="openpyxl")
else:
continue
with gr.Row():
gr.Markdown(f"**{file.name}**")
source_col = gr.Dropdown(
df.columns.tolist(), label="Source Column", interactive=True)
target_col = gr.Dropdown(
df.columns.tolist(), label="Target Column", interactive=True)
source_lang = gr.Textbox(
label="Source Language", placeholder="e.g., English", interactive=True)
target_lang = gr.Textbox(
label="Target Language", placeholder="e.g., French", interactive=True)
selections.extend(
[source_col, target_col, source_lang, target_lang])
except Exception as e:
gr.Markdown(f"Error processing {file.name}: {str(e)}")
def process_files(*args):
results = []
args = [tuple(args[i:i + 4]) for i in range(0, len(args), 4)]
out = ""
for file, (source_col, target_col, source_lang, target_lang) in zip(files, args):
out = file + "::" + source_col + "::" + target_col + \
"::" + source_lang + "::" + target_lang
results.append(out)
return "\n".join(results)
submit_button.click(
fn=process_files, inputs=selections, outputs=output_text)
submit_button = gr.Button("Submit & Process", interactive=True)
output_text = gr.Markdown()
demo.launch()
1 Like