You want people to learn when the stakes are low. This is better for them, and it's better for all of us. School should gradually go from low stakes to higher stakes, not be a low-stakes zone the whole time that then tosses people into the real world. Otherwise you're presented with terrible choices like expelling a 20 year old for a habit they learned when they were 8 and never got called on, vs letting them get away with continuing to cheat.
Making it easy to cheat and lie when the stakes are low helps create situations like "we can't trust anyone who says they know how to program so we have to waste a lot of interview time on tedious crap."
The first solution that occurs to me seems to be smaller class sizes and differently structured assignments with more of a "tell me about why you wrote this" type interactive stuff. The same way you'd do when looking at someone's github, to see how deep their understanding of the code there goes.