macOS下Python3.6 pickle兼容报错:需类字节对象而非str
Hey there, let's break down exactly what's going on here and fix those frustrating errors you're hitting. The core issue is that Python 3 strictly separates Unicode strings (str) and binary data (bytes), whereas Python 2 treated them almost interchangeably. Your pickle and file I/O code needs to adapt to this clear distinction.
Let's Diagnose the Errors
- "a bytes-like object is required, no 'str'": This pops up when you pass a string to a function expecting binary data—like using
pickle.load()on a file opened in text mode ('r') instead of binary mode ('rb'). - "write() argument must be str, not bytes": This is the flip side: you’re trying to write binary data (like the output of
pickle.dumps()) to a file opened in text mode ('w') instead of binary mode ('wb').
Step-by-Step Fixes for Your Parameter Saving Code
Since your code saves model parameters with pickle, here's how to adjust it properly for Python 3:
1. Always Use Binary Mode for Pickle Files
Pickle serializes data into binary format, so you must use 'rb' (read binary) and 'wb' (write binary) for all file operations tied to pickle. Never mix text modes ('r'/'w') with pickle operations.
2. Use pickle.dump() and pickle.load() Directly
You don’t need to manually handle pickle.dumps()/pickle.loads() plus file write()/read()—these methods handle binary I/O cleanly on their own.
Here's the corrected code for your parameter saving logic:
# Saving parameters (replace your existing save code with this) if iter % SAVE_PARAMS_EVERY == 0: # Open file in WRITE BINARY mode with open('params.pkl', 'wb') as f: # pickle.dump() writes the serialized object directly to the binary file pickle.dump(params, f) # Loading parameters (if you need to load them later) with open('params.pkl', 'rb') as f: # pickle.load() reads the binary data and reconstructs your object params = pickle.load(f)
3. Handling Legacy Python 2 Pickle Files
If you’re loading a pickle file saved with Python 2, add the encoding='latin1' parameter to pickle.load() to fix the string/bytes mismatch between versions:
with open('old_python2_params.pkl', 'rb') as f: params = pickle.load(f, encoding='latin1')
Why Your Earlier Attempts Caused Confusion
- If you switched to
'wb'but usedpickle.dumps(params)(which returns abytesobject) and tried writing it to a text-mode file, you’d get the "write() must be str" error. - If you used
'rb'but tried reading the file as a string first (instead of lettingpickle.load()handle it), you’d hit the "bytes-like object required" error.
Sticking to binary modes and using pickle.dump()/pickle.load() directly eliminates these mismatches entirely.
内容的提问来源于stack exchange,提问作者jaymikaelson

