```json
{
  "sym_variables": [
    ("x0", "strips of bacon"),
    ("x1", "pickles"),
    ("x2", "knishes")
  ],
  "objective_function": "7*x0 + 6*x1 + 6*x2",
  "constraints": [
    "19*x0 + 1*x1 + 4*x2 <= 172",
    "19*x0 + 6*x1 + 4*x2 <= 197",
    "13*x0 + 11*x1 + 12*x2 <= 250",
    "16*x0 + 13*x1 + 14*x2 <= 190",
    "19*x0 + 6*x1 >= 21",
    "19*x0 + 6*x1 + 4*x2 >= 51",
    "13*x0 + 11*x1 >= 79",
    "13*x0 + 12*x2 >= 68",
    "11*x1 + 12*x2 >= 64",
    "19*x0 + 4*x2 <= 97",
    "1*x1 + 4*x2 <= 121",
    "19*x0 + 1*x1 + 4*x2 <= 121",  
    "19*x0 + 6*x1 <= 105",
    "6*x1 + 4*x2 <= 106",
    "19*x0 + 6*x1 + 4*x2 <= 106",
    "11*x1 + 12*x2 <= 97",
    "13*x0 + 12*x2 <= 176",
    "13*x0 + 11*x1 + 12*x2 <= 176",
    "16*x0 + 14*x2 <= 162",
    "16*x0 + 13*x1 <= 82",
    "16*x0 + 13*x1 + 14*x2 <= 82",
    "x0 == int",
    "x1 == int"
  ]
}
```

```python
import gurobipy as gp

try:
    # Create a new model
    m = gp.Model("food_optimization")

    # Create variables
    bacon = m.addVar(vtype=gp.GRB.INTEGER, name="bacon")
    pickles = m.addVar(vtype=gp.GRB.INTEGER, name="pickles")
    knishes = m.addVar(vtype=gp.GRB.CONTINUOUS, name="knishes")


    # Set objective function
    m.setObjective(7 * bacon + 6 * pickles + 6 * knishes, gp.GRB.MAXIMIZE)

    # Add constraints
    m.addConstr(19 * bacon + 1 * pickles + 4 * knishes <= 172, "fat_constraint")
    m.addConstr(19 * bacon + 6 * pickles + 4 * knishes <= 197, "fiber_constraint1")
    m.addConstr(13 * bacon + 11 * pickles + 12 * knishes <= 250, "umami_constraint1")
    m.addConstr(16 * bacon + 13 * pickles + 14 * knishes <= 190, "carbs_constraint1")
    m.addConstr(19 * bacon + 6 * pickles >= 21, "fiber_constraint2")
    m.addConstr(19 * bacon + 6 * pickles + 4 * knishes >= 51, "fiber_constraint3")
    m.addConstr(13 * bacon + 11 * pickles >= 79, "umami_constraint2")
    m.addConstr(13 * bacon + 12 * knishes >= 68, "umami_constraint3")
    m.addConstr(11 * pickles + 12 * knishes >= 64, "umami_constraint4")
    m.addConstr(19 * bacon + 4 * knishes <= 97, "fat_constraint2")
    m.addConstr(1 * pickles + 4 * knishes <= 121, "fat_constraint3")
    m.addConstr(19 * bacon + 1 * pickles + 4 * knishes <= 121, "fat_constraint4")
    m.addConstr(19 * bacon + 6 * pickles <= 105, "fiber_constraint4")
    m.addConstr(6 * pickles + 4 * knishes <= 106, "fiber_constraint5")
    m.addConstr(19 * bacon + 6 * pickles + 4 * knishes <= 106, "fiber_constraint6")
    m.addConstr(11 * pickles + 12 * knishes <= 97, "umami_constraint5")
    m.addConstr(13 * bacon + 12 * knishes <= 176, "umami_constraint6")
    m.addConstr(13 * bacon + 11 * pickles + 12 * knishes <= 176, "umami_constraint7")
    m.addConstr(16 * bacon + 14 * knishes <= 162, "carbs_constraint2")
    m.addConstr(16 * bacon + 13 * pickles <= 82, "carbs_constraint3")
    m.addConstr(16 * bacon + 13 * pickles + 14 * knishes <= 82, "carbs_constraint4")


    # Optimize model
    m.optimize()

    if m.status == gp.GRB.OPTIMAL:
        print('Obj: %g' % m.objVal)
        print('bacon: %g' % bacon.x)
        print('pickles: %g' % pickles.x)
        print('knishes: %g' % knishes.x)
    elif m.status == gp.GRB.INFEASIBLE:
        print('The model is infeasible.')
    elif m.status == gp.GRB.UNBOUNDED:
        print('The model is unbounded.')
    else:
        print('Optimization ended with status %d' % m.status)


except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))

except AttributeError:
    print('Encountered an attribute error')
```