如何将以元组和列表为键值的字典写入文本文件及JSON写入报错解决
Hey there! Let's break down your two Python questions with practical, actionable solutions:
First off, plain text files don't natively understand Python's complex types like tuples as dictionary keys—but we've got a few solid ways to handle this:
Option 1: Use pickle (Best for Python-only use cases)
Pickle is Python's built-in serialization tool that can handle almost all native Python types, including dictionaries with tuples as keys or lists as values. It stores data in a binary format, so it's efficient for large data too.
Example Code:
import pickle # Your sample dictionary with tuple keys and list values my_dict = {(1, 2): ["a", "b"], (3, 4): ["c", "d"]} # Write to file with open("my_dict.pkl", "wb") as f: pickle.dump(my_dict, f) # Read it back later with open("my_dict.pkl", "rb") as f: loaded_dict = pickle.load(f) print(loaded_dict) # Output: {(1, 2): ['a', 'b'], (3, 4): ['c', 'd']}
Note: Pickle files are Python-specific, so you can't read them with other languages. Also, never load pickle files from untrusted sources—they can execute malicious code.
Option 2: Manual Serialization with ast.literal_eval (For human-readable text)
If you want a plain text file that's somewhat readable, you can convert the dictionary to a string and use ast.literal_eval (safer than eval()) to parse it back.
Example Code:
import ast my_dict = {(1, 2): ["a", "b"], (3, 4): ["c", "d"]} # Write to text file with open("my_dict.txt", "w") as f: f.write(str(my_dict)) # Read it back with open("my_dict.txt", "r") as f: file_content = f.read() loaded_dict = ast.literal_eval(file_content) print(loaded_dict) # Same as original
Pro Tip: ast.literal_eval only parses safe Python literals, so it won't execute arbitrary code like eval() does.
JSON has strict rules—it only allows strings as dictionary keys, and can't serialize types like tuples, datetime objects, or custom classes. That's almost certainly why you're getting a TypeError. Here's how to fix it:
Option 1: Custom JSON Encoder
Create a custom encoder to handle non-JSON-friendly types by converting them to compatible formats.
Example Code:
import json class CustomJSONEncoder(json.JSONEncoder): def default(self, obj): # Convert tuples to lists (since JSON doesn't support tuple keys) if isinstance(obj, tuple): return list(obj) # If the key is a non-string type, convert it to a string elif isinstance(obj, (int, float, bool)): return str(obj) # For other non-serializable objects, adjust as needed (e.g., datetime -> isoformat) return super().default(obj) # Your large dictionary with tuple keys large_dict = {(1, "foo"): [10, 20], ("bar", 3): ["x", "y"]} # Write with custom encoder with open("large_dict.json", "w") as f: # Use `indent` for readability (optional for large files) json.dump(large_dict, f, cls=CustomJSONEncoder) # To read it back, you'll need to convert keys back to tuples if needed with open("large_dict.json", "r") as f: loaded_dict = json.load(f) # Convert list keys back to tuples fixed_dict = {tuple(k): v for k, v in loaded_dict.items()} print(fixed_dict) # Restores original tuple keys
Option 2: Preprocess the Dictionary
If you don't want to write a custom encoder, manually convert all non-JSON-compatible elements before serialization:
import json large_dict = {(1, "foo"): [10, 20], ("bar", 3): ["x", "y"]} # Convert tuple keys to strings processed_dict = {str(k): v for k, v in large_dict.items()} # Write to JSON with open("large_dict.json", "w") as f: json.dump(processed_dict, f) # Read back and convert keys to tuples if needed with open("large_dict.json", "r") as f: loaded_dict = json.load(f) fixed_dict = {ast.literal_eval(k): v for k, v in loaded_dict.items()}
Note: Use ast.literal_eval instead of eval() here if your keys have untrusted content.
Option 3: Switch to pickle or shelve (For Large, Python-Only Data)
If JSON isn't a hard requirement, pickle (as shown in the first question) or shelve (which acts like a persistent dictionary) are great for large datasets. They handle all Python types natively, so you won't hit serialization errors.
内容的提问来源于stack exchange,提问作者subhasree ghosh

