Após uma investigação mais aprofundada, o problema parece derivar do fato de que o programa tem um identificador de arquivo aberto para o arquivo de dispositivo da porta serial quando o modem desconecta da porta USB 1 . Meu palpite é que o kernel envia SIGHUP para informar ao programa da desconexão. Isso é bem tratado pelo Python sem erros e o programa é executado sem qualquer problema quando executado normalmente. No entanto, parece que o systemd intercepta o sinal SIGHUP e o trata como uma falha, matando o programa. Modificar o programa para funcionar de forma diferente ignorou o problema.
1: O motivo para manter o identificador de arquivo aberto é que, depois de enviar o comando de desligamento, o programa aguarda até que o modem envie uma mensagem indicando que ele foi totalmente desligado. Infelizmente, o modem desconecta-se do USB imediatamente após o envio da mensagem, o que não dá tempo suficiente para que o programa analise a resposta e, em seguida, feche o identificador de arquivo.