I want to define a constant that should be available in all of the submodules of a package. I’ve thought that the best place would be in in the __init__.py file of the root package. But I don’t know how to do this. Suppose I have a few subpackages and each with several modules. How can I access that variable from these modules?
Of course, if this is totally wrong, and there is a better alternative, I’d like to know it.
回答 0
您应该能够将它们放入__init__.py。这一直都在做。
mypackage/__init__.py:
MY_CONSTANT =42
mypackage/mymodule.py:
from mypackage import MY_CONSTANT
print"my constant is", MY_CONSTANT
然后,导入mymodule:
>>>from mypackage import mymodule
my constant is42
You should be able to put them in __init__.py. This is done all the time.
mypackage/__init__.py:
MY_CONSTANT = 42
mypackage/mymodule.py:
from mypackage import MY_CONSTANT
print "my constant is", MY_CONSTANT
Then, import mymodule:
>>> from mypackage import mymodule
my constant is 42
Still, if you do have constants, it would be reasonable (best practices, probably) to put them in a separate module (constants.py, config.py, …) and then if you want them in the package namespace, import them.
mypackage/__init__.py:
from mypackage.constants import *
Still, this doesn’t automatically include the constants in the namespaces of the package modules. Each of the modules in the package will still have to import constants explicitly either from mypackage or from mypackage.constants.
You cannot do that. You will have to explicitely import your constants into each individual module’s namespace. The best way to achieve this is to define your constants in a “config” module and import it everywhere you require it:
You can define global variables from anywhere, but it is a really bad idea. import the __builtin__ module and modify or add attributes to this modules, and suddenly you have new builtin constants or functions. In fact, when my application installs gettext, I get the _() function in all my modules, without importing anything. So this is possible, but of course only for Application-type projects, not for reusable packages or modules.
And I guess no one would recommend this practice anyway. What’s wrong with a namespace? Said application has the version module, so that I have “global” variables available like version.VERSION, version.PACKAGE_NAME etc.
Just wanted to add that constants can be employed using a config.ini file and parsed in the script using the configparser library. This way you could have constants for multiple circumstances. For instance if you had parameter constants for two separate url requests just label them like so:
I found the documentation on the Python website very helpful. I am not sure if there are any differences between Python 2 and 3 so here are the links to both:
How can I return an integer value from this function when an object is created?
I wrote a program, where __init__ does command line parsing and I need to have some value set. Is it OK set it in global variable and use it in other member functions? If so how to do that? So far, I declared a variable outside class. and setting it one function doesn’t reflect in other function ??
回答 0
__init__必须返回无。您不能(或至少不应该)返回其他东西。
尝试做任何您想返回的实例变量(或函数)。
>>>classFoo:...def __init__(self):...return42...>>> foo =Foo()Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: __init__() should returnNone
As a special constraint on constructors, no value may be returned; doing so will cause a TypeError to be raised at runtime.
As a proof, this code:
class Foo(object):
def __init__(self):
return 2
f = Foo()
Gives this error:
Traceback (most recent call last):
File "test_init.py", line 5, in <module>
f = Foo()
TypeError: __init__() should return None, not 'int'
回答 3
有问题的示例用法如下:
classSampleObject(object):def __new__(cls, item):if cls.IsValid(item):return super(SampleObject, cls).__new__(cls)else:returnNonedef __init__(self, item):
self.InitData(item)#large amount of data and very complex calculations...ValidObjects=[]for i in data:
item =SampleObject(i)if item:# in case the i data is valid for the sample objectValidObjects.append(item)
Sample Usage of the matter in question can be like:
class SampleObject(object):
def __new__(cls, item):
if cls.IsValid(item):
return super(SampleObject, cls).__new__(cls)
else:
return None
def __init__(self, item):
self.InitData(item) #large amount of data and very complex calculations
...
ValidObjects = []
for i in data:
item = SampleObject(i)
if item: # in case the i data is valid for the sample object
ValidObjects.append(item)
I do not have enough reputation so I can not write a comment, it is crazy! I wish I could post it as a comment to weronika
The __init__ method, like other methods and functions returns None by default in the absence of a return statement, so you can write it like either of these:
class Foo:
def __init__(self):
self.value=42
class Bar:
def __init__(self):
self.value=42
return None
But, of course, adding the return None doesn’t buy you anything.
I’m not sure what you are after, but you might be interested in one of these:
class Foo:
def __init__(self):
self.value=42
def __str__(self):
return str(self.value)
f=Foo()
print f.value
print f
The Python import mechanism works relative to the __name__ of the current file. When you execute a file directly, it doesn’t have its usual name, but has "__main__" as its name instead. So relative imports don’t work.
You can, as Igancio suggested, execute it using the -m option. If you have a part of your package that is meant to be run as a script, you can also use the __package__ attribute to tell that file what name it’s supposed to have in the package hierarchy.
Then, since in this case ‘components’ and ‘tests’ are siblings folders, you can import the relative module either using the insert or the append method of the sys.path module.
Something like:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
Otherwise, you can launch your script with the ‘-m’ argument (note that in this case, we are talking about a package, and thus you must not give the ‘.py’ extension), that is:
python -m pkg.tests.core_test
In such a case, you can simply use the relative import as you were doing:
from ..components.core import GameLoopEvents
You can finally mix the two approaches, so that your script will work no matter how it is called.
For example:
if __name__ == '__main__':
if __package__ is None:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
else:
from ..components.core import GameLoopEvents
If your use case is for running tests, and it seams that it is, then you can do the following. Instead of running your test script as python core_test.py use a testing framework such as pytest. Then on the command line you can enter
$$ py.test
That will run the tests in your directory. This gets around the issue of __name__ being __main__ that was pointed out by @BrenBarn. Next, put an empty __init__.py file into your test directory, this will make the test directory part of your package. Then you will be able to do
from ..components.core import GameLoopEvents
However, if you run your test script as a main program then things will fail once again. So just use the test runner. Maybe this also works with other test runners such as nosetests but i haven’t checked it. Hope this helps.
Old thread. I found out that adding an __all__= ['submodule', ...] to the
__init__.py file and then using the from <CURRENT_MODULE> import * in the target works fine.
You can use from pkg.components.core import GameLoopEvents, for example I use pycharm, the below is my project structure image, I just import from the root package, then it works:
This approach worked for me and is less cluttered than some solutions:
try:
from ..components.core import GameLoopEvents
except ValueError:
from components.core import GameLoopEvents
The parent directory is in my PYTHONPATH, and there are __init__.py files in the parent directory and this directory.
The above always worked in python 2, but python 3 sometimes hit an ImportError or ModuleNotFoundError (the latter is new in python 3.6 and a subclass of ImportError), so the following tweak works for me in both python 2 and 3:
try:
from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
from components.core import GameLoopEvents
If someone is looking for a workaround, I stumbled upon one. Here’s a bit of context. I wanted to test out one of the methods I’ve in a file. When I run it from within
if __name__ == "__main__":
it always complained of the relative imports. I tried to apply the above solutions, but failed to work, since there were many nested files, each with multiple imports.
Here’s what I did. I just created a launcher, an external program that would import necessary methods and call them. Though, not a great solution, it works.
This is very confusing, and if you are using IDE like pycharm, it’s little more confusing.
What worked for me:
1. Make pycharm project settings (if you are running python from a VE or from python directory)
2. There is no wrong the way you defined. sometime it works with
from folder1.file1 import class
if it does not work, use
import folder1.file1
3. Your environment variable should be correctly mentioned in system or provide it in your command line argument.