docs: def from_string(rxn_string):
          """
          Generates a balanced reaction from a string. The reaction must
          already be balanced.
  
          Args:
              rxn_string:
                  The reaction string. For example, "4 Li + O2-> 2Li2O"
  
          Returns:
              BalancedReaction
          """
          rct_str, prod_str = rxn_string.split("->")
  
          def get_comp_amt(comp_str):
              return {Composition(m.group(2)): float(m.group(1) or 1)
                      for m in re.finditer(r"([\d\.]*(?:[eE]-?[\d\.]+)?)\s*([A-Z][\w\.\(\)]*)",
                                           comp_str)}
          return BalancedReaction(get_comp_amt(rct_str), get_comp_amt(prod_str))