datetime.datetime has microsecond precision, and if you want to reconstruct a datetime from microseconds since the Unix epoch in a provided timezone, you can do:
(datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(microseconds=timestamp_us)).astimezone(tz)
This is a general solution, but it constructs two extra datetimes and a timedelta on the way. datetime.fromtimestamp could bring that to just the one, but it takes float seconds, so there's no way to avoid losing precision (for far enough date in the future, but well short of datetime.max). One solution is to handle the micros separately:
datetime.fromtimestamp(timestamp_us // 1000000, tz).replace(microsecond=timestamp_us % 1000000)
This still requires constructing two datetimes, and it bakes in an assumption that the timezone offset doesn't affect and isn't affected by the millisecond component. (Which probably is the case! I think.)
This might all be too much thought about edge cases that don't matter, but given the *_ns() functions in the time module (PEP 564), I'm curious why datetime doesn't have a constructor that takes an integer timestamp with the full precision that supports.
Peace,
-Sam