Not to deobfuscate, but Rizin[1][2] supports disassembling the Python bytecode for both 2.x and 3.x versions out of the box.
[1] https://rizin.re
[1] https://rizin.re
A naive disassembler (like the `dis` module in python) interprets the bytecode linearly -- i.e. one instruction after another. Rizin's diassembler [2] seems to take the same approach. The way I do disassembly is to only disassemble code paths that are potentially executed by queueing non-conditional jumps, both targets of a conditional jump, and the next instruction when the current instruction is non-jumping instruction.
[1] https://github.com/landaire/unfuck/wiki/Obfuscation-Tricks
[2] https://github.com/rizinorg/rizin/blob/e3d1b967854c33cf9dfbb...