如何发送带DataFrame附件的邮件?CSV附件版本异常问题求助
Hey there, let's break down your two main issues and fix them one by one:
1. Why Are You Sending the Old CSV File?
The most likely culprits here are unflushed file caches or mismatched working directories—super common pitfalls when dealing with file I/O and automation. Here's how to fix it:
a. Make Sure Your CSV Write Operation Is Fully Completed
If you're using pandas to modify and save the CSV, double-check that the save operation finishes before you send the email. Pandas' to_csv() method handles file closing automatically, but if you're manually opening files, always use a with statement to avoid leaving files in an unflushed state:
import pandas as pd # Load and modify your data df = pd.read_csv('CC.csv') # ... your data edits here ... # Save properly (pandas handles closing the file) df.to_csv('CC.csv', index=False)
b. Use Absolute File Paths Instead of Relative Ones
When you use filename='CC.csv', your script looks for the file in its current working directory—which might not be the folder you think, especially when launching via a Unix executable on Mac. To eliminate this ambiguity, use an absolute path:
import os # Get the folder where your script lives script_folder = os.path.dirname(os.path.abspath(__file__)) # Build the full path to your CSV filename = os.path.join(script_folder, 'CC.csv')
c. Force Fresh File Reads
If you're still seeing old data, disable buffering when opening the file to ensure you read the latest version from disk:
attachment = open(filename, 'rb', buffering=0)
2. How to Send a DataFrame Directly as an Attachment
You don't need to save the DataFrame to a CSV file first! You can convert it to an in-memory CSV stream and attach that directly—this skips all the file I/O headaches entirely. Here's a complete working example:
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders import pandas as pd from io import BytesIO # Email configs email_user = 'Bot@gmail.com' email_password = 'Business101' email_send = ('myemail@gmail.com', 'myfriendsemail@gmail.com') subject = 'TOP 5 CONTRACTS' # Set up the email msg = MIMEMultipart() msg['From'] = email_user msg['To'] = ",".join(email_send) msg['Subject'] = subject # Add email body body = 'These are the latest contracts for this week!' msg.attach(MIMEText(body, 'plain')) # Replace this with your actual DataFrame top_5_contracts = pd.DataFrame({ 'Contract ID': ['C001', 'C002', 'C003', 'C004', 'C005'], 'Client': ['Alpha Corp', 'Beta Inc', 'Gamma LLC', 'Delta Group', 'Eta Co'], 'Value': [12000, 25000, 18000, 32000, 21000] }) # Convert DataFrame to an in-memory CSV stream csv_stream = BytesIO() top_5_contracts.to_csv(csv_stream, index=False) csv_stream.seek(0) # Reset the stream to the start so we can read it # Create the attachment part = MIMEBase('application', 'octet-stream') part.set_payload(csv_stream.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', f"attachment; filename=CC.csv") msg.attach(part) # Send the email text = msg.as_string() server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login(email_user, email_password) server.sendmail(email_user, email_send, text) server.quit() print("Emailed Recipients")
Why This Method Is Better:
- No more worrying about file caches or wrong paths—everything stays in memory
- Faster and cleaner for automation workflows (no temporary files cluttering up your system)
- Eliminates the risk of sending old files entirely
Quick Check for Your Mac Unix Executable
When launching via a Unix executable, confirm your script's working directory matches where your CSV lives. Add this line at the start of your script to debug:
import os print("Current working directory:", os.getcwd())
If it's not the right folder, use the absolute path trick from earlier to fix it.
内容的提问来源于stack exchange,提问作者user14425857

