在我工作的一个大型应用程序中,几个人以不同的方式导入相同的模块,例如 导入 x 或者 从 y 导入 x 其副作用是 x 被导入两次,如果有人依赖全局属性,可能会引入非常微妙的错误
例如假设我有一个包含三个文件 mymodule.py、main.py 和 init.py
的包 mypakcagemymodule.py 内容
l = []
class A(object): pass
main.py 内容
def add(x):
from mypackage import mymodule
mymodule.l.append(x)
print "updated list",mymodule.l
def get():
import mymodule
return mymodule.l
add(1)
print "lets check",get()
add(1)
print "lets check again",get()
它打印
updated list [1]
lets check []
updated list [1, 1]
lets check again []
因为现在在两个不同的模块中有两个列表,同样类A是不同的 对我来说,这看起来很严重,因为类本身将受到不同的对待 例如下面的代码打印 False
def create():
from mypackage import mymodule
return mymodule.A()
def check(a):
import mymodule
return isinstance(a, mymodule.A)
print check(create())
问题:
有什么办法可以避免这种情况吗?除了强制该模块应该以一种方式导入 onyl 之外。这不能通过 python 导入机制处理,我在 django 代码和其他地方也看到了几个与此相关的错误。
最佳答案
每个模块命名空间只导入一次。问题是,您以不同的方式导入它们。第一个是从全局包导入,第二个是本地非打包 import。 Python 认为模块是不同的。第一个导入在内部缓存为 mypackage.mymodule,第二个仅作为 mymodule。
解决这个问题的方法是始终使用绝对导入。也就是说,始终为您的模块提供从顶级包开始的绝对导入路径:
def add(x):
from mypackage import mymodule
mymodule.l.append(x)
print "updated list",mymodule.l
def get():
from mypackage import mymodule
return mymodule.l
请记住,您的入口点(您运行的文件 main.py)也应该在包的外部。当您希望入口点代码位于包内时,通常您会改用运行一个小脚本。示例:
runme.py,包外:
from mypackage.main import main
main()
然后在 main.py 中添加:
def main():
# your code
我找到了 this document由 Jp Calderone 撰写,是关于如何(不)构建 Python 项目的重要提示。按照它你不会有问题。注意 bin 文件夹 - 它在包外。我将在此处复制整个文本:
Filesystem structure of a Python project
Do:
- name the directory something related to your project. For example, if your project is named "Twisted", name the top-level directory for its source files
Twisted. When you do releases, you should include a version number suffix:Twisted-2.5.- create a directory
Twisted/binand put your executables there, if you have any. Don't give them a.pyextension, even if they are Python source files. Don't put any code in them except an import of and call to a main function defined somewhere else in your projects.- If your project is expressable as a single Python source file, then put it into the directory and name it something related to your project. For example,
Twisted/twisted.py. If you need multiple source files, create a package instead (Twisted/twisted/, with an emptyTwisted/twisted/__init__.py) and place your source files in it. For example,Twisted/twisted/internet.py.- put your unit tests in a sub-package of your package (note - this means that the single Python source file option above was a trick - you always need at least one other file for your unit tests). For example,
Twisted/twisted/test/. Of course, make it a package withTwisted/twisted/test/__init__.py. Place tests in files likeTwisted/twisted/test/test_internet.py.- add
Twisted/READMEand Twisted/setup.pyto explain and install your software, respectively, if you're feeling nice.Don't:
- put your source in a directory called
srcorlib. This makes it hard to run without installing.- put your tests outside of your Python package. This makes it hard to run the tests against an installed version.
- create a package that only has a
__init__.pyand then put all your code into__init__.py. Just make a module instead of a package, it's simpler.- try to come up with magical hacks to make Python able to import your module or package without having the user add the directory containing it to their import path (either via
PYTHONPATHor some other mechanism). You will not correctly handle all cases and users will get angry at you when your software doesn't work in their environment.
关于python - 如果从不同的路径导入模块重新导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1459236/
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or