unable to import function in django/python - python

I am writing a django project with follwing files:
ttam_container
-utils.py
-ttam
-views.py
Codes within utils.py module:
def random_string():
...
def remove_blanks():
...
...other functions...
Codes within views.py:
from utils import *
def get_sequences(request):
...
string = random_string()
...
sequences = remove_blanks(sequences_with_blanks)
...
The error global name remove_blanks' is not defined is then reported. I thought I didn't import the utils.py correcty in the first place, but the random_string works...
Any idea what's happening?

The import should be:
from utils import remove_blanks
without .py

The correct import would be:
import sys
sys.path.append("..")
from utils import random_string, remove_blanks
Modules must be in one of the directories in sys.path. This is initialized to the value of $PYTHONPATH, or some default if $PYTHONPATH is not set. For example:
$ python
Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python26.zip', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-cyg
win', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/pytho
n2.6/lib-dynload', '/usr/lib/python2.6/site-packages']
So if your module isn't in that path, you need to append the right path ('..' in this case) to sys.path.

Related

I have problem with import class from another (Python)

The problem is that I can not import class from another folder. Class that I want to import in LoginPage.py.
# login.py
from selenium import webdriver
import time
import unittest
from Selenium.POMProjectDemo.Pages.LoginPage import LoginPage
class loginTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome(executable_path='D:\python\Selenium\chrome_driver\chromedriver.exe')#, options = webdriver.ChromeOptions())
#options.add_experimental_option('excludeSwitches', ['enable-logging'])
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
def test_01_login_valid(self):
driver = self.driver
driver.get('https://vk.com/')
login = LoginPage(driver)
login.enter_user_name()
login.enter_user_password()
login.login_button
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
print('test completed')
#Loginpage.py
from Selenium.POMProjectDemo.Locators.Locators import locators
from auth_data import vk_password,vk_login
from POMProjectDemo.Locators import Locators
class LoginPage():
def __init__(self, driver):
self.driver = driver
self.index_email_id = locators.index_email_id
self.index_pass_id = locators.index_pass_id
self.loginButton_id = locators.loginButton_id
def enter_user_name(self):
self.driver.find_element_by_id(self.loginField_id).clear()
self.driver.find_element_by_id(self.loginField_id).send_keys(vk_login)
def enter_user_password(self):
self.driver.find_element_by_id(self.passwordField_id).clear()
self.driver.find_element_by_id(self.passwordField_id).send_keys(vk_password)
def login_button(self):
self.driver.find_element_by_id(self.loginButton_id).click()
Error:
ModuleNotFoundError: No module named 'Selenium'
The way python figures out import paths is to first look at entries in sys.path and check if the module you are trying to import is accessible from any of the paths. It will stop at the first path under which your module is found.
e.g.
>>> sys.path
['', '/home/bhakta/dev/sonar/controller/venv/lib/python37.zip', '/home/bhakta/dev/sonar/controller/venv/lib/python3.7', '/home/bhakta/dev/sonar/controller/venv/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7', '/home/bhakta/dev/sonar/controller/venv/lib/python3.7/site-packages']
Let's say you have a module called "some_module" in /tmp
➜ ll /tmp/some_module
total 4
-rw-rw-r-- 1 bhakta bhakta 29 Jan 11 11:39 __init__.py
➜ cat /tmp/some_module/__init__.py
def foo():
print("Hello")
➜ python
Python 3.7.10 (default, Oct 19 2021, 17:50:56)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append("/tmp")
>>> import some_module
>>>
>>>
>>> some_module.foo()
Hello
Now, lets say you have
➜ ll /var/tmp/some_module
total 4
-rw-rw-r-- 1 bhakta bhakta 45 Jan 11 11:43 __init__.py
➜ cat /var/tmp/some_module/__init__.py
def foo():
print("From var/tmp Hello")
And you do:
➜ python
Python 3.7.10 (default, Oct 19 2021, 17:50:56)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append("/tmp")
>>> sys.path.append("/var/tmp")
>>>
>>>
>>> import some_module
>>>
>>>
>>> some_module.foo()
Hello
Notice that python found the first system path (/tmp) where some_module was found.
Thus:
➜ python
Python 3.7.10 (default, Oct 19 2021, 17:50:56)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append("/var/tmp")
>>> sys.path.append("/tmp")
>>> import some_module
>>>
>>> some_module.foo()
From var/tmp Hello

Why sys.path.insert not using the latest python package?

List below is my project structure.
├── folder1
├── test.py
├── folder2
├── A.py
├── folder3
├── A.py
A.py in folder2 and folder3 are the same except self.key
#folder2
class TestAPI():
def __init__(self):
self.key = 50
#folder3
class TestAPI():
def __init__(self):
self.key = 100
In test.py, the code is
import sys
root_path = '/user/my_account'
sys.path.insert(0, root_path + '/folder2')
from A import TestAPI
test_api = TestAPI()
print(test_api.key)
sys.path.insert(0, root_path + '/folder3')
from A import TestAPI
test_api = TestAPI()
print(test_api.key)
print(sys.path)
While executing test.py, it returns 50,50, ['/user/my_account/folder3', '/user/my_account/folder2']. Why the second time from A import TestAPI not from folder3 but folder2?
Edit: If I'd like to import TestAPI from folder3 for the second time, is there a way to 'delete' the PYTHONPATH after import TestAPI from folder2?
I would change your TestAPI code (A.py) into a commons folder (one that can be imported by other codes) and then have:
class TestAPI():
def __init__(self, key):
self.key = key
Then in your test.py you can do something like:
import sys
root_path = '/user/my_account'
sys.path.insert(0, root_path + '/commons')
from commons.A import TestAPI
test_api_50 = TestAPI(50)
print(test_api_50.key)
test_api_100 = TestAPI(100)
print(test_api_100.key)
I can edit this if there's an issue/typo.
Note that python folder/packaging is worth reading about. Your future self will thank you.
importlib.reload solve my question.
import sys
root_path = '/user/my_account'
sys.path.insert(0, root_path + '/folder2')
import A
test_api = A.TestAPI()
print(test_api.key)
sys.path.insert(0, root_path + '/folder3')
import importlib
importlib.reload(A) # should reload after inserting PYTHONPATH and before import A
import A
test_api = A.TestAPI()
print(test_api.key)
print(sys.path)
sys.path is a list. So just use the append method.
Also, you don't need root path. just run
sys.path.append('folder2')
Edit: demo that prooves that it works
[luca#artix stackoverflow]$ mkdir my_module
[luca#artix stackoverflow]$ ed my_module/foo.py
?my_module/foo.py
i
print('From foo')
.
wq
18
[luca#artix stackoverflow]$ python
Python 3.9.1 (default, Feb 6 2021, 13:49:29)
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'foo'
>>> import sys
>>> sys.path.append('my_module')
>>> import foo
From foo
>>>

Python moving modules into sub directory (without breaking existing import structure)

Supposing I am writing library code with a directory structure as follows:
- mylibrary/
|
|-----foo.py
|-----bar.py
|-----baz.py
|-----__init__.py
And to better organise I create a sub directory:
- mylibrary/
|
|-----foobar/
| |-----foo.py
| |-----bar.py
|-----baz.py
|-----__init__.py
I want all client code to keep working without updates so I want to update init.py so that imports don't break.
I've tried adding this to init.py:
from foobar import foo
Now if I open a shell I can do:
from mylibrary import foo
print(foo.Foo)
However if I do this:
from mylibrary.foo import Foo
I get No module named mylibrary.foo error.
Here is the traceback from my actual example:
Type "help", "copyright", "credits" or "license" for more information.
>>> from global_toolkit import section
>>> section.Section
<class 'global_toolkit.serialization.section.Section'>
>>> from global_toolkit.section import Section
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'global_toolkit.section'
>>>
Can anyone explain this behaviour?
Add this in your __init__.py :
from .foobar import foo, bar
import sys
for i in ['foo','bar']:
sys.modules['mylib.'+i] = sys.modules['mylib.foobar.'+i]
Now, from mylib.foo import Foo should work.

When can import find a module when nothing else can?

In short, how can this happen?
cternus#astarael:~⟫ python
Python 2.7.12 (default, Jun 29 2016, 14:05:02)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import backports
>>> import imp
>>> imp.find_module('backports')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named backports
The imp module claims to be "an interface to the mechanisms used to implement the import statement." If this is so, why can the import statement find backports, but imp.find_module() can't?
For some background: backports claims to be a "namespace package," not a package in its own right; other modules, such as backports.shutil_get_terminal_size, are situated in this namespace. This formed the basis of an ultimately-rejected PEP. I'm asking this question because I'm having a variant of this issue and am trying to track down the cause.
For more weirdness:
>>> backports.__file__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__file__'
>>> dir(backports)
['__doc__', '__name__', '__path__']
>>> backports.__path__
['/Library/Python/2.7/site-packages/backports']
>>> import os; os.path.exists(backports.__path__[0])
False
(And no, I have no files or directories named backports or backports.py anywhere on my system.)
Edited to clarify: I am aware that this probably represents a strange configuration state of my system. My question is not "how can I fix this" but "how is it possible?"
This module can be brought by python-configparser APT package.
how is it possible?
This is possible because python-configparser uses path configuration file (.pth file):
root#ubuntu18.10:/# dpkg -L python-configparser | head | tail -n 1
/usr/lib/python2.7/dist-packages/configparser-3.5.0b2-nspkg.pth
This file is automatically picked up by python's site module on interpreter startup because it is located in /usr/lib/python2.7/dist-packages/ and has .pth extension. As docs say:
A path configuration file is a file whose name has the form name.pth and exists in one of the four directories mentioned above...
Lines starting with import (followed by space or tab) are executed.
The file /usr/lib/python2.7/dist-packages/configparser-3.5.0b2-nspkg.pth contains the following:
import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('backports', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('backports', [os.path.dirname(p)])));m = m or sys.modules.setdefault('backports', types.ModuleType('backports'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
So, this code is auto-executed on python startup. Slightly beautified, it looks like this:
import sys, types, os
has_mfs = sys.version_info > (3, 5)
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',))
importlib = has_mfs and __import__('importlib.util')
has_mfs and __import__('importlib.machinery')
m = has_mfs and sys.modules.setdefault('backports', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('backports', [os.path.dirname(p)])))
m = m or sys.modules.setdefault('backports', types.ModuleType('backports'))
mp = (m or []) and m.__dict__.setdefault('__path__',[])
(p not in mp) and mp.append(p)
What it does (at least on python 2) is: it manually creates a module object by invoking types.ModuleType constructor (that's why it looks like <module 'backports' (built-in)>) and puts it to sys.modules with sys.modules.setdefault('backports', types.ModuleType('backports')). After it was added to sys.modules, import backports will just return that object.
__path__ gives a hint
root#ubuntu18.10:/# python -c 'import backports; print backports.__path__'
['/usr/lib/python2.7/dist-packages/backports']
root#ubuntu18.10:/# dpkg -S /usr/lib/python2.7/dist-packages/backports
python-configparser: /usr/lib/python2.7/dist-packages/backports
I have no files or directories named backports
On Ubuntu, there is /usr/lib/python2.7/dist-packages/backports brought by this package as shown above, so I'm not sure why you don't have it. Maybe it's another package behaving similarly/variant of it for MacOS is different/you just deleted that dir while debugging the issue?

Dynamically importing Python module

I have a trusted remote server that stores many custom Python modules. I can fetch them via HTTP (e.g. using urllib2.urlopen) as text/plain, but I cannot save the fetched module code to the local hard disk. How can I import the code as a fully operable Python module, including its global variables and imports?
I suppose I have to use some combination of exec and imp module's functions, but I've been unable to make it work yet.
It looks like this should do the trick: importing a dynamically generated module
>>> import imp
>>> foo = imp.new_module("foo")
>>> foo_code = """
... class Foo:
... pass
... """
>>> exec foo_code in foo.__dict__
>>> foo.Foo.__module__
'foo'
>>>
Also, as suggested in the ActiveState article, you might want to add your new module to sys.modules:
>>> import sys
>>> sys.modules["foo"] = foo
>>> from foo import Foo
<class 'Foo' …>
>>>
Here's something I bookmarked a while back that covers something similar:
Customizing the Python Import System
It's a bit beyond what you want, but the basic idea is there.
Python3 version
(attempted to edit other answer but the edit que is full)
import imp
my_dynamic_module = imp.new_module("my_dynamic_module")
exec("""
class Foo:
pass
""", my_dynamic_module.__dict__)
Foo = my_dynamic_module.Foo
foo_object = Foo()
# register it on sys
import sys
sys.modules[my_dynamic_module.__name__] = my_dynamic_module
I recently encountered trying to do this while trying to write unit tests for source code examples I put into a project's readme (I wanted to avoid just linking to small files or duplicating the text in a way that could get out of sync).
I came up with the following
import sys
import types
from importlib import import_module
def compile_and_install_module(module_name: str, source_code: str) -> types.ModuleType:
"""Compile source code and install it as a module.
End result is that `import <module_name>` and `from <module_name> import ...` should work.
"""
module = types.ModuleType(module_name, "Module created from source code")
# Execute source in context of empty/fake module
exec(source_code, module.__dict__)
# Insert fake module into sys.modules. It's now a real module
sys.modules[module_name] = module
# Imports should work now
return import_module(module_name)
And a quick example of how you can use it
$ cat hello.py
def foo():
print("Hello world")
bar = 42
$ python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from compile import compile_and_install_module
>>> compile_and_install_module("hello", open("hello.py").read())
<module 'hello'>
>>> import hello
>>> hello.foo()
Hello world
>>> from hello import bar
>>> bar
42
You can remove the return value and import_lib import if you

Categories

Resources