Pyomo中Constraint.Skip无法被识别的原因是什么?
问题描述
我掌握在Pyomo中使用规则创建表达式的方法,但尝试使用Constraint.Skip时,它无法被识别为有效属性,以下是最小复现示例:
import pyomo.environ as pe m = pe.ConcreteModel() m.x = pe.Var() from constraint import * def expression_rule(m, i): if i: # generate the constraint expr = 0 <= m.x else: # skip this index expr = Constraint.Skip return expr n=2 m.constraints_skip_rule = pe.Constraint(range(n), rule = expression_rule)
我查阅源码时明确看到Constraint.Skip在多处被使用,且constraint.py文件顶部的__all__列表中也包含Constraint项,为何上述代码中无法识别该属性?是否我对Python库的工作机制存在基础认知疏漏?
问题根因
错误来自from constraint import *这行导入造成的命名空间污染:
- PyPI上存在一个独立的第三方约束求解库叫
python-constraint,它的顶层导入名就是constraint,这个库的Constraint类和Pyomo的约束类完全无关,本身没有Skip属性。 - 星号导入会把这个无关第三方库的所有导出对象拉到当前作用域,直接替换掉了原本可以通过Pyomo访问的同名
Constraint类,自然会报属性不存在的错误。 - 你查阅的
constraint.py是Pyomo安装路径下的内部子模块文件,和你导入的顶层constraint第三方包不是同一个对象,这里确实存在Python导入机制的认知疏漏:Python导入时会优先匹配环境中已安装的顶层包,不会自动将子模块内的同名对象暴露到顶层命名空间。
修复方案
直接删除错误的from constraint import *导入语句,通过Pyomo的命名空间访问Constraint.Skip即可,修正后可运行的代码如下:
import pyomo.environ as pe m = pe.ConcreteModel() m.x = pe.Var() def expression_rule(m, i): if i: expr = 0 <= m.x else: expr = pe.Constraint.Skip return expr n=2 m.constraints_skip_rule = pe.Constraint(range(n), rule = expression_rule)
如果你确实需要同时使用python-constraint这个第三方库,不要使用星号导入,给库起别名避免命名冲突,例如写为import constraint as csp。
内容的提问来源于stack exchange,提问作者makansij
相关产品推荐
相关产品推荐

