I have two files foo.py and bar.py
foo.py
NAME = os.getenv('NAME').lower()
bar.py
from foo import NAME
def helper():
print (NAME)
I have a test file test/test_name.py
import bar
#mock.patch('bar.NAME', "Alice")
def test__get_file(monkeypatch):
print(bar.NAME)
Giving an error:
../bar.py:6: in <module>
from foo import NAME
../foo.py:17: in <module>
NAME = os.getenv('NAME').lower()
E AttributeError: 'NoneType' object has no attribute 'lower'
What I am missing?
A per os module documentation, os.getenv can return a default value if the environment variable does not exist.
So, you could modify foo.py to avoid raising an error when running your test (for the reason given by #MrBeanBremen in his comment) like this:
NAME = os.getenv('NAME', default="MISSING").lower()
Related
I am having trouble creating an importable Python package/library/module or whatever the right nomenclature is. I am using Python 3.7
The file structure I am using is:
Python37//Lib//mypackage
mypackage
__init__.py
mypackage_.py
The code in __init__.py is:
from mypackage.mypackage_ import MyClass
The code in mypackage_.py is:
class MyClass:
def __init__(self, myarg = None):
self.myvar = myarg
And from my desktop I try running the following code:
import mypackage
x = MyClass(None)
But get the following error:
Traceback (most recent call last):
File "C:\Users\***\Desktop\importtest.py", line 3, in <module>
x = MyClass(None)
NameError: name 'MyClass' is not defined
You haven't imported the name MyClass into your current namespace. You've imported mypackage. To access anything within mypackage, you need to prefix the name with mypackage.<Name>
import mypackage
x = mypackage.MyClass(None)
As #rdas says, you need to prefix the name with mypackage.<Name>.
I don't recommend doing this, but you can wildcard import in order to make x = MyClass(None) work:
from mypackage import *
Now, everything from mypackage is imported and usable in the current namespace. However, you have to be careful with wildcard imports because they can create definition conflictions (if multiple modules have the same name for different things).
I'm trying to call a static method of a class from a different module and getting:
AttributeError: ClassObject instance has no attribute 'foo1'
Things are structures like this:
a.py file content:
class Conf():
def __init__(self,......):
.
.
.
#staticmethod
def foo1():
.
.
.
b.py file content:
from a import Conf
Conf.foo1()
What am I doing wrong?
You are calling your method in the good way, so maybe you are not importing the module.
Check which file is loaded as a.py in b.py:
import a
print a.__file__
This will print which file is loaded.
I'm trying to do a dynamic import (using "__import__()") of a submodule in web2py and it doesn't seem to be finding the submodule.
Here's an example path:
web2py/app/modules/module.py <-- This works
web2py/app/modules/module_folder/submodule.py <-- This won't get spotted.
Right now as a workaround I'm using 'exec()' but I'd rather not do that.
Answers to questions:
"Do you have __init__.py in module_folder?"
Yep.
"What exactly is the line of code you write to import web2py/app/modules/module_folder/submodule.py?"
mapping_module = __import__('communication_templates.mappings.%s' % module_name)
"what is the error?"
<type 'exceptions.AttributeError'> 'module' object has no attribute 'mapping_dict'
Explanation: I'm trying to get a variable named 'mapping_dict' from the module once I've loaded it.
The problem here is that __import__ does not do the most intuitive thing (neither does import btw).
Here's what happens:
>>> import sys
>>> x = __import__('package1.package2.module')
>>> x
<module 'package1' from 'C:\\Temp\\package1\\__init__.py'>
Even though package1.package2.module was imported, the variable returned is actually package1.
So, to access something that is in package1.package2.module, one has to dig down again:
>>> x.package2.module.Class
<class 'package1.package2.module.Class'>
Is it then the same as importing just package1?
Not really:
>>> x = __import__('package1')
>>> x
<module 'package1' from 'C:\\Temp\\package1\\__init__.py'>
>>> x.package2.module.Class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'package1' has no attribute 'package2'
Why?
Well, __import__ is the same as `import, that is, these are the same:
package1 = __import__('package1.package2.module')
# is the same as:
import package1.package2.module
And:
package1 = __import__('package1')
# is the same as:
import package1
In each of those cases, you get just one local variable package1.
In the case of importing package1.package2.module, package2 is also imported and stored in package2 attribute of package package1 etc.
Solution
To access package1.package2.module.Class, if package1.package2.module is in a string:
>>> s = 'package1.package2.module'
>>> module = __import__(s)
>>> for submodule_name in s.split('.')[1:]:
... module = getattr(module, submodule_name)
...
>>> module.Class
<class 'package1.package2.module.Class'>
I have a function called prepared_db in submodule db.db_1:
from spam import db
submodule_name = "db_1"
func_name = "prepare_db"
func = ...
how can I get the function by the submodule name and function name in the context above?
UPDATE:
To respond #histrio 's answer, I can verify his code works for os module. But it does not work in this case. To create the example:
$ mkdir -p spam/db
$ cat > spam/db/db_1.py
def prepare_db():
print('prepare_db func')
$ touch spam/db/__init__.py
$ PYTHONPATH=$PYTHONPATH:spam
now, you can do the import normally:
>>> from spam.db.db_1 import prepare_db
>>> prepare_db()
prepare_db func
but if you do this dynamically, I get this error:
>>> getattr(getattr(db, submodule_name), func_name)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-1b6aa1216551> in <module>()
----> 1 getattr(getattr(db, submodule_name), func_name)
AttributeError: module 'spam.db.db_1' has no attribute 'prepared_db'
It's simple. You can consider module as object.
import os
submodule_name = "path"
func_name = "exists"
submodule = getattr(os, submodule_name)
function = getattr(submodule, func_name)
function('/home') # True
or [just for fun, don't do that]
fn = reduce(getattr, ('sub1', 'sub2', 'sub3', 'fn'), module)
UPDATE
import importlib
submodule = importlib.import_module('.'+submodule_name, module.__name__)
function = getattr(submodule, func_name)
I think I figured it out, you need to add the function to the __all__ variable in the __init__.py file, so that would be something along the lines of:
from .db_1 import prepare_db
__all__ = ['prepare_db']
After that, it should work just fine.
Im pretty new to python, and have been having a rough time learning it. I have a main file
import Tests
from Tests import CashAMDSale
CashAMDSale.AMDSale()
and CashAMDSale
import pyodbc
import DataFunctions
import automa
from DataFunctions import *
from automa.api import *
def AMDSale():
AMDInstance = DataFunctions.GetValidAMD()
And here is GetValidAMD
import pyodbc
def ValidAMD(GetValidAMD):
(short method talking to a database)
My error comes up on the line that has AMDInstance = DataFunctions.GetValidAMD()
I get the error AttributeError: 'module' object has no attribute 'GetValidAMD'
I have looked and looked for an answer, and nothing has worked. Any ideas? Thanks!
DataFunctions is a folder, which means it is a package and must contain an __init__.py file for python to recognise it as such.
when you import * from a package, you do not automatically import all it's modules. This is documented in the docs
so for your code to work, you either need to explicitly import the modules you need:
import DataFunctions.GetValidAMD
or you need to add the following to the __init__.py of DataFunctions:
__all__ = ["GetValidAMD"]
then you can import * from the package and everything listen in __all__ will be imported
When you create the file foo.py, you create a python module. When you do import foo, Python evaluates that file and places any variables, functions and classes it defines into a module object, which it assigns to the name foo.
# foo.py
x = 1
def foo():
print 'foo'
>>> import foo
>>> type(foo)
<type 'module'>
>>> foo.x
1
>>> foo.foo()
foo
When you create the directory bar with an __init__.py file, you create a python package. When you do import bar, Python evaluates the __init__.py file and places any variables, functions and classes it defines into a module object, which it assigns to the name bar.
# bar/__init__.py
y = 2
def bar():
print 'bar'
>>> import bar
>>> type(bar)
<type 'module'>
>>> bar.y
2
>>> bar.bar()
bar
When you create python modules inside a python package (that is, files ending with .py inside directory containing __init__.py), you must import these modules via this package:
>>> # place foo.py in bar/
>>> import foo
Traceback (most recent call last):
...
ImportError: No module named foo
>>> import bar.foo
>>> bar.foo.x
1
>>> bar.foo.foo()
foo
Now, assuming your project structure is:
main.py
DataFunctions/
__init__.py
CashAMDSale.py
def AMDSale(): ...
GetValidAMD.py
def ValidAMD(GetValidAMD): ...
your main script can import DataFunctions.CashAMDSale and use DataFunctions.CashAMDSale.AMDSale(), and import DataFunctions.GetValidAMD and use DataFunctions.GetValidAMD.ValidAMD().
Check out this.
It's the same problem. You are importing DataFunctions which is a module. I expct there to be a class called DataFunctions in that module which needs to be imported with
from DataFunctions import DataFunctions
...
AMDInstance = DataFunctions.GetValidAMD()