Comparing a team ID with a player ID (owner) is not good. Should then also be pUnit.getTeam(). And
!=
, right? And, if you also check whether the unit has left, the team/ player ID check for that should be the same as for the arrival check.
I don't think a timer for destroying the unit will be any easier than a timer for the ExtraHappiness itself. It could easily be destroyed with a per-turn probability. Not sure how you'd get the AI to keep the unit in place. Even if HappinessTimer is used (which wouldn't require the unit to stay), there's a question of how to get the AI to send the unit to foreign cities. Maybe you already have a plan for that? This whole idea seems pretty similar to the Foment Unhappiness espionage mission, but I guess that's no help if you want to tie the effect to a promotion that any unit could receive.
For a timer implemented in Python, you'd need to store the remaining turns of any active timers along with the IDs of the cities that the timers refer to; and you'd need to turn that data into a script data string and send that to the DLL through CyCity.setScriptData (just) before the game gets saved; and restore the data from the script data string to be obtained from the DLL after loading a savegame. For some of these steps, it's clear when they should happen (set the timer on onUnitMove, decrease it at the start of a player turn), but, for others, I'm not sure. There's also a class PyCity (as opposed to CyCity) that could perhaps store the timer values; don't know if that's how persistent city data should be implemented in Python. In other words, I'm no real help for this approach.
This guide seems to deal with this very subject.