使用Python发起POST请求导入CSV时遇ValueError:已关闭文件I/O操作
Fixing "ValueError: I/O operation on closed file" When POSTing CSV Data with Python Requests
Let’s break down why this error is happening and how to fix it quickly.
The Root Cause
Your code has a classic timing issue here:
- The
csv.reader()creates an iterator that relies on the open file handle to read data. - When your
withblock finishes, Python automatically closes theCars.csvfile. - But
requests.request()doesn’t actually process thepayload(your csv.reader object) until it sends the POST request—after the file is already closed. That’s why you get the "I/O operation on closed file" error.
Solution 1: Keep the File Open During the Request (Best for Large Files)
The simplest fix is to move your POST request inside the with block, so the file stays open while requests reads it. Even better—you don’t need csv.reader at all here, because requests can directly handle the open file object for CSV uploads:
import requests url = "https://paneledgesandbox.//API/v3/surveys/id/import-responses" headers = { 'X-API-TOKEN': 'zzzz', 'Content-Type': 'text/csv', 'Cookie': 'CPSessID=bb5b5cf55ceff2c2b8237810db3ca3a7; XSRF-TOKEN=XSRF_0wG1WMbV3G0ktBb' } # Keep the file open while sending the request with open('Cars.csv', 'r') as file: response = requests.request("POST", url, headers=headers, data=file) print(response.text)
This works because requests streams the file content directly (without loading the whole thing into memory), which is efficient for large CSVs.
Solution 2: Load CSV Data into Memory (For Small Files)
If you need to modify the CSV data before sending it, you can read all the content into memory first (so it’s no longer tied to the file handle):
import requests import csv import io url = "https://paneledgesandbox.//API/v3/surveys/id/import-responses" headers = { 'X-API-TOKEN': 'zzzz', 'Content-Type': 'text/csv', 'Cookie': 'CPSessID=bb5b5cf55ceff2c2b8237810db3ca3a7; XSRF-TOKEN=XSRF_0wG1WMbV3G0ktBb' } with open('Cars.csv', 'r') as file: # Read all CSV rows into a list rows = list(csv.reader(file)) # Convert the list back to a CSV-formatted string output_buffer = io.StringIO() csv_writer = csv.writer(output_buffer) csv_writer.writerows(rows) payload = output_buffer.getvalue() # Now the payload is independent of the file, which is safe to send response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
Key Takeaways
withblocks do close files automatically, but you must ensure any operation that needs the open file happens inside the block.csv.readeris lazy—it only reads the file when you iterate over it.requestsdoes this iteration when sending the request, not when you assigndata=payload.- For file uploads, always prefer passing the open file object directly to
requests(Solution 1) unless you need to modify the data first.
内容的提问来源于stack exchange,提问作者Aanurag Das




