Part 1 (of 3)
As suggested by @JohanC commented out #bbox=bbox_props to remove boxes, changed 1*np.sign(x) to 1.4*np.sign(x) to spread labels wider along X, computed percentages perc[i] and added them to labels inside ax.annotate(...). Final picture looks like (code below picture):

Final Code:
Try it online!
data = {'a_column': 20, 'b_column': 130,
'c_column': 140, 'd_column': 300, 'e_column': 150,
'f_column': 170, 'g_column': 10, 'h_column': 20, 'i_column': 250,'j_column': 54}
base_d = sum(list(data.values()))
final_data = {k:m/base_d*100 for k,m in data.items()}
final_data
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5), subplot_kw=dict(aspect="equal"))
recipe = list(final_data.keys())
data = list(final_data.values())
perc = [str(round(e / s * 100., 1)) + '%' for s in (sum(data),) for e in data]
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40)
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
#bbox=bbox_props,
zorder=0, va="center")
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1)/2. + p.theta1
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = "angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle": connectionstyle})
ax.annotate(recipe[i] + ' ' + perc[i], xy=(x, y), xytext=(1.4*np.sign(x), 1.4*y),
horizontalalignment=horizontalalignment, **kw)
plt.show()
Part 2 (of 3)
If you have very many data entries then default coloring of pie chart doesn't look good, it has just 10-15 unique colors. I decided to make my own custom coloring based on rainbow colors. In my coloring even if you have 100 data entries then all colors are unique. In code below coloring is done inside ax.pie(... colors = ....). I made example image and code for rainbow coloring:

Try it online!
import numpy as np, math, random
import matplotlib.pyplot as plt
random.seed(0)
data = {f'dat_{str(i).zfill(2)}' : random.random() for i in range(49)}
base_d = sum(list(data.values()))
final_data = {k:m/base_d*100 for k,m in data.items()}
fig, ax = plt.subplots(figsize=(12, 5), subplot_kw=dict(aspect="equal"))
recipe = list(final_data.keys())
data = list(final_data.values())
perc = [str(round(e / s * 100., 1)) + '%' for s in (sum(data),) for e in data]
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40,
colors = (lambda C = 7: [plt.cm.gist_rainbow((i % C) / C + i // C * 1 / C / math.ceil(len(data) / C)) for i in range(len(data))])())
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
#bbox=bbox_props,
zorder=0, va="center")
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1)/2. + p.theta1
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = "angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle": connectionstyle})
ax.annotate(recipe[i] + ' ' + perc[i], xy=(x, y), xytext=(1.4*np.sign(x), 1.4*y),
horizontalalignment=horizontalalignment, **kw)
plt.show()
Part 3 (of 3)
Also decided to improve the case of very many entries (around 100 entries). Did next improvements: 1) separated along X odd and even entries. 2) put all labels uniformly along Y (before they were uniform along angle). 3) made smaller font.

Try it online!
import numpy as np, math, random
import matplotlib.pyplot as plt
np.random.seed(0)
random.seed(0)
data = {f'dat_{str(i).zfill(2)}' : random.random() for i in range(98)}
base_d = sum(list(data.values()))
final_data = {k:m/base_d*100 for k,m in data.items()}
fig, ax = plt.subplots(figsize=(12, 5), subplot_kw=dict(aspect="equal"))
recipe = list(final_data.keys())
data = list(final_data.values())
perc = [str(round(e / s * 100., 2)) + '%' for s in (sum(data),) for e in data]
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40, radius = 0.8,
colors = (lambda C = 7: [plt.cm.gist_rainbow((i % C) / C + i // C * 1 / C / math.ceil(len(data) / C)) for i in range(len(data))])())
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
#bbox=bbox_props,
zorder=0, va="center")
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1) / 2. + p.theta1
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
yc = np.arcsin(y) / (np.pi / 2)
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = f'angle,angleA=0,angleB={ang}'
kw["arrowprops"].update({"connectionstyle": connectionstyle})
ax.annotate(recipe[i] + ' ' + perc[i], xy = (0.8 * x, 0.8 * y), xytext = ((1.0 + (i % 2) * 0.4) * np.sign(x), 1.4 * yc),
horizontalalignment = horizontalalignment, fontsize = 'x-small', **kw)
plt.show()