It can't be done automatically because imported can execute code. Since that's part of the semantics, you have to be lazy by hand.
In any case, given your points, it seems like a future Python version ought to introduce a new version of the import statement with lazy semantics (which, besides eliminating dead code, is also IMO the more correct/explicit behavior when importing symbols).
class LazyModule:
def __init__(self, name):
self.name = name
def __getattr__(self, key):
mod = {}
exec('import %s as mod', mod)
self.mod = mod['mod']
return getattr(self.mod, key)
class LazyImporter:
def get_module(self, name):
return LazyModule(name)