Categories: Python

Validating Cross-platform File Transfers

I often need to copy files from my MacBook to my Windows desktop. For some files, I especially want to ensure that they were copied correctly (no data loss or any changes to the files). Therefore, I wrote a Python script that takes a directory and enumerates all the files under that directory, computes their SHA 256 hashes, and writes these hashes to a file. As a final step, I compute the SHA 256 hash of the file containing the list of file/digest pairs. Under this setup, I just need to run the script on each machine after copying a directory and verify that it generates the same final SHA 256 hash. This guarantees that the probability of an error in the file transfer is extremely tiny. One of the issues I ran into was this Python error:

$ python /c/repos/scratchpad/scripts/python/write_sha256.py . --concat-hashes hashes.txt
[2026-07-31 12:51:12] Processing: .\._somefile.dat
Traceback (most recent call last):
  File "C:\repos\scratchpad\scripts\python\write_sha256.py", line 79, in <module>
    process_concat(args.directory, args.concat_hashes, force=args.force)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\repos\scratchpad\scripts\python\write_sha256.py", line 54, in process_concat
    concat_file.write(f"{sha256sum}  {relpath}\n")
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python314\Lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'charmap' codec can't encode character '\u202f' in position 107: character maps to <undefined>

This had to be the Windows code page keeping things exciting! I explicitly set the encoding to UTF-8 to prevent such issues. For the final hashes to be identical, the list of files in the source directory needs to match the list of files in the destination directory. However, this wasn’t the case when copying files from my MacBook Pro to my Windows machine. I had never stopped to figure out what all these files with a leading period and underscore were whenever I did such a copy: they are AppleDouble files, which are used to store extended attributes/metadata (see description at AppleSingle and AppleDouble formats – Wikipedia). I don’t care about such files when validating my file copies so I made a change to ignore them by default.

The last issue was the line endings of the file. On windows, how would I detect the line ending of a file? – Stack Overflow wasn’t much help but since I’m using the Git Bash environment, the file command suggested in linux – How to find out line-endings in a text file? – Stack Overflow was perfect. For the hashes to be identical, the files on both platforms should have the same line endings. I updated the script to write the text files with LF line terminators.

$ file hashes-macos.txt
hashes-macos.txt: Unicode text, UTF-8 text

$ file hashes.txt
hashes.txt: Unicode text, UTF-8 text, with CRLF line terminators

I already had a change in place to iterate over the files in alphabetical order (which is a stable ordering). With this implementation, I no longer need to tar/compress files or verify hashes for individual files.


Categories: Python

No module named ‘encodings’ Stumps Python N00b.

I tried running a program on my desktop recently and got this error:

$ python myscript.py
Fatal Python error: Failed to import encodings module
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x0000b500 (most recent call first):
  <no Python frame>

I had realized that I was accumulating Python installations, so I uninstalled the older versions from my machine. I still had a valid 3.13 installation, so this error was confusing to me. I ensured there were no other versions on my machine.

$ python --version
Python 3.13.3

$ py -0
 -V:3.13 *        Python 3.13 (64-bit)

$ py -0p
 -V:3.13 *        C:\Python313\python.exe

I decided to uninstall 3.14 and install 3.14 since I’m in cleanup mode anyway. This gave me an opportunity to review the active python releases and their end of life dates on the Download Python | Python.org page. I found it interesting that the installer itself is being retired (here’s the More info link).

Once installation of 3.14 was done, I was surprised to find that the problem was still there!

$ python --version
Python 3.14.6

$ python myscript.py
Fatal Python error: Failed to import encodings module
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007edc (most recent call first):
  <no Python frame>

$ which python
/c/Python314/python

$ /c/Python314/python myscript.py
Fatal Python error: Failed to import encodings module
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007f60 (most recent call first):
  <no Python frame>

I consulted my AI assistant and its next recommendation was to check for corrupted environment variables! Look at this culprit!

$ echo $PYTHONHOME
C:\Python311\

All I needed to do to this fix was to clear the PYTHONHOME environment variable.

$ export PYTHONHOME=

I also deleted it from the “User variables for saint” section of the Environment Variables dialog box.