/!\ In the post by @nominal-animal there are sign errors in this presentation (at least leading up to the calculation of s and t). The correct s and t are given by the following Python routine that uses SymPy:
def close_points(l1, l2):
"""return s and t, the parametric location of the closest
points on l1 and l2, the actual points, and the separation between
those two points.
NOTE: these were checked on wolframalpha.com with query, e.g.
"closest points on Line((0,0,0),(1,1,1)) and Line((0,1,0),(1,2,3))"
Examples
========
>>> from sympy import Line
>>> close_points(Line((0, 0, 0), (1, 1, 1)), Line((0, 1, 0), (1, 2, 3)))
(3/4, 1/4, Point3D(3/4, 3/4, 3/4), Point3D(1/4, 5/4, 3/4), sqrt(2)/2)
>>> close_points(Line((0, 0, 0), (1, 2, 3)), Line((1, 1, 1), (2, 3, 5)))
(7/5, 4/5, Point3D(7/5, 14/5, 21/5), Point3D(9/5, 13/5, 21/5), sqrt(5)/5)
"""
# L1 = lambda s: l1.p1+s*l1.direction
# L2 = lambda t: l2.p1+t*l2.direction
# eq = lambda l1: Matrix(L1(var('s')) - L2(var('t'))).dot(l1.direction)
# stdict = solve((
# eq(Line(var('x1 y1 z1'),var('x2 y2 z2'))),
# eq(Line(var('x3 y3 z3'),var('x4 y4 z4')))),
# var('s t'), dict=True)
x1,y1,z1 = l1.p1
x2,y2,z2 = l1.p2
x3,y3,z3 = l2.p1
x4,y4,z4 = l2.p2
x21, y21, z21 = l1.direction
x43, y43, z43 = l2.direction
x31, y31, z31 = l2.p1 - l1.p1
R1 = x21**2 + y21**2 + z21**2
R2 = x43**2 + y43**2 + z43**2
d4321 = x21*x43 + y21*y43 + z21*z43
d3121 = x21*x31 + y21*y31 + z21*z31
d4331 = x31*x43 + y31*y43 + z31*z43
den = d4321**2 - R1*R2
# R1*s - d4321*t - d3121 = 0
# d4321*s - R2*t - d4331 = 0
s = (d4321*d4331 - R2*d3121)/den
t = (R1*d4331 - d4321*d3121)/den
ps = l1.p1 + s*l1.direction
pt = l2.p1 + t*l2.direction
return s, t, ps, pt, ps.distance(pt)