Python:Pickle与str()+eval()存储Redis字典,孰更高效?哪种是最佳实践?
str()+eval() vs. pickle for Redis Dictionary Storage: Efficiency & Best Practices Great question! Let's dive into the tradeoffs between these two approaches, focusing on both performance and what's considered best practice in Python development.
Efficiency
When it comes to speed and size, pickle is the clear winner:
- Serialization/Deserialization Speed:
pickleis purpose-built for serializing Python objects into a compact binary format. Thepickle.dumps()andpickle.loads()operations are optimized at the C level (in CPython), making them significantly faster than converting a dict to a string withstr()and parsing it back witheval().eval()has to parse human-readable text as Python code, which adds a lot of overhead—especially for large or nested dictionaries. - Data Size: A pickled dict is almost always smaller in byte size than the string representation from
str(). Text-based representations have to include extra characters like braces, quotes, and commas that don't add any actual data value, bloating the storage footprint in Redis.
Best Practices
This is where the gap really widens—str()+eval() is never a good choice for production code, and here's why:
1. Critical Security Risks
eval() executes arbitrary Python code. If an attacker gains access to your Redis instance (or if untrusted data ends up in there), they could replace your stored dict string with malicious code (e.g., os.system('rm -rf /')) and eval() would run it directly. This is a catastrophic security vulnerability that's avoidable with any other serialization method.
While pickle isn't completely risk-free (loading untrusted pickle data can also execute arbitrary code), it's a binary format—tampering with it to inject malicious code is far more complex than modifying a plain text string. And if you're only storing data from trusted sources (which you should be when using pickle), this risk is manageable.
2. Object Compatibility
str() only works reliably with basic built-in types. If your dict contains custom class instances, str() will just output something like <__main__.User object at 0x10a2b3c>, which eval() can't convert back into a usable object. pickle, on the other hand, can serialize most Python objects (including custom classes) as long as the class definition exists in the environment where you're deserializing.
3. Maintainability & Readability
While str() produces human-readable text (which might seem like a plus), the security risks far outweigh this benefit. If you need human-readable data in Redis, consider using JSON instead—json.dumps() and json.loads() are safe, cross-language compatible, and still produce readable text.
4. Redis Compatibility
Both methods work with Redis's string storage, but pickle is more straightforward: you can directly store the bytes returned by pickle.dumps() and load them with pickle.loads() without extra encoding/decoding steps. With str(), you have to encode the string to bytes before storing, then decode it back before running eval()—adding unnecessary complexity.
Final Recommendations
- Avoid
str()+eval()entirely: The security risk is unacceptable, and it's slower and less flexible than alternatives. - Use JSON for basic types: If you're only storing dicts with strings, numbers, lists, and other JSON-serializable types,
jsonis the best choice—it's safe, readable, and works with non-Python applications. - Use
picklefor complex Python objects: When you need to serialize custom classes or other Python-specific types,pickleis the right tool. Just ensure your Redis data comes from trusted sources, and be mindful of version compatibility (pickle formats can vary between Python versions).
内容的提问来源于stack exchange,提问作者Soubriquet

