Cannot import local module in Python despite trying multiple suggestions - python

I've read through about ten posts on how to import local modules, and I'm still stumped on why this isn't working. I have an extremely simple module, actor.py, with a single class inside it:
class Actor(object):
def __init__(self, name, age):
self.name = name
self.age = age
I'm trying to import it into another module, scraper.py, within the same directory:
Some fixes have listed not having init.py as being a problem with local imports, so I know that's not my problem.
Initially I tried these:
import actor
and
from actor import Actor
but it tells me that actor and Actor are unresolved references. here tells me that's Python 2 syntax, and I'm using Python 3. That answer instead recommends that I do:
from .actor import Actor
When I run my program with that syntax, I get this error:
ModuleNotFoundError: No module named '__main__.actor'; '__main__' is not a package
So I go searching again, and this post tells me to remove the dot from 'actor,' but as stated before, I've tried that as well. My final guess was
from . import actor
but that yields
ImportError: cannot import name 'actor'
which I follow to here, but the answers there mention circular dependencies, and I'm certain actor and scraper have none. Am I perhaps not writing my module correctly? I can't think of any other ways to write an import statement.
edit: if it helps at all, I'm using Intellij

Try from WebScraper.actor import Actor. If this doesn't work its because your package directory is not in the PYTHONPATH. You can set that in the IntelliJ Python run configuration.
The relative import is not working for you because you are trying to run a module as a script. You can see an explanation of what is happening at https://stackoverflow.com/a/8300343/7088038. If you want relative imports to work you will have to add a __main__.py file to your module to allow it to be runnable, or execute from an external script where you use an absolute import so you don't clobber the package namespace.
One other stylistic note- usually (but not always) package names in python use all lowercase names. CamelCase is reserved for class names. So if you wanted to follow convention you would call your package webscraper and use from webscraper.actor import Actor

To import a class into your script use:
from actor import Actor
Or to import the .py entirely (including whatever imports included in it) into the namespace use:
from actor import *

Related

Python3 unable to find a package module

I have a file called dns_poison.py that needs to call a package called netscanner. When i try and load the icmpscan module from dns_poison.py I get this message:
ModuleNotFoundError: No module named 'icmpscan'
I've done a sys.path and can confirm that the correct path is in place. The files are located at D:\PythonProjects\Networking\tools and D:\PythonProjects appears when I do a sys.path.
Here is my directory structure:
dns_poison.py
netscanner/
__init__.py
icmpscan.py
Code snippets for the files are as follows:
dns_poison.py
import netscanner
netscanner\__init__.py
from icmpscan import ICMPScan
netscanner\icmpscan.py
class ICMPScan:
def __init__(self, target, count=2, timeout=1):
self.target = target
self.count = count
self.timeout = timeout
self.active_hosts = []
# further code below here....
I don't understand why it cannot find the module, as I've used this exact same method on other python projects without any problems. Any help would be much appreciated.
When you run python dns_poison.py, the importer checks the module path then the local directory and eventually finds your netscanner package that has the following available:
netscanner
netscanner.icmpscan
netscanner.icmpscan.ICMPScan
Now I ask you, where is just icmpscan? The importer cannot find because well, it doesnt exist. The PYTHONPATH exists at wherever dns_poison.py resides, and doesn't append itself to include the absolute path of any imported modules because that simply not how it works. So netscanner can be found because its at the same level as dns_poison.py, but the importer has no clue where icmpscan.py exists because you havent told it. So you have two options to alter your __init__.py:
from .icmpscan import ICMPScan which works with Python 3.x
from netscanner.icmpscan import ICMPScan which works with both Python 2.x/3.x
Couple of references for you:
Python Import System
Python Modules recommend you ref section 6.4.2 Intra-package References
The most simple way to think about this is imports should be handled relative to the program entry-point file. Personally I find this the most simple and fool-proof way of handling import paths.
In your example, I would have:
from netscanner.icmpscan import ICMPScan
In the main file, rather than add it to init.py.

Importing class from file in parent directory

I have python code that is structured like this:
src
--->commoncode.py
--->folder1
--->file1.py
--->folder2
--->file2.py
--->folder3
--->file3.py
I want to use the code that is in commoncode.py in the files fileN.py. I have tried includingfrom . import commoncode but that does not work (ImportError: cannot import name 'commoncode').
I am able to use the code with import commoncode if I include a symlink in each of the subfolders but that seems hacky and sort of defeats the purpose of having common code.
The only code in commoncode.py right now is class commoncode():.
Let me know if there is any information that I can further provide that would be useful.
Since you're not using packages, one way is to modify your path:
import sys
sys.path.insert(0, "..")
from commoncode import <whatever>
# Now you can access imported symbols from commoncode.py
usually when importing you need to import as follows,
from (Name of the module) import (name of the class within the module).
so in your case, if I understood correctly I believe it would be:
from (Name of the common code module) import commoncode.
at the top of any of your modules you wish to use commoncode in, this is how it would be imported.
Please make sure that you haven't missed any capital or lowercase letters as well, as it is case sensitive when you import. Hope this could be of some help.

Python : from module import * in __init__

Here is a simple case: I want to define a module in python name robot. So, I have a folder named robot with these two files:
__init__.py:
from test import a
test.py:
a = "hello world"
Now, when I import robot in the interpreter, the robot namespace includes test and a. However, I only want it to include a. Why this odd behavior?
EDIT:
Here's a slightly more representative example of what I want to achieve:
Given the following files:
__init__.py:
from spam import a
import ham
spam.py:
a = "hello world"
ham.py:
b = "foo"
Can I have a robot namespace containing a and ham at its top level but not spam?
You have created not just a module but a package. A package contains its submodules in its namespace (once they have been imported, as you imported test here). This is as it should be, since the usual way of using packages is to provide a grouping of several modules. There's not much use to making a package with only one module (i.e., one contentful .py file) inside it.
If you just want a one-file module, just create a file called robots.py and put your code in there.
Edit: See this previous question. The answer is that you should in general not worry about excluding module names from your package namespace. The modules are supposed to be in the package namespace. If you want to add functions and stuff from submodules as well, for convenience, that's fine, but there's not really anything to be gained by "covering your tracks" and hiding the modules you imported. However, as described in the answers to that question, there are some hackish ways to approximate what you want.
Are you just asking how to import specific modules or functions?
test.py:
import robot.spam.a
import robot.ham
Don't import the entire package.

Import statement in library definition does not seem to be executed

I am having a problem that may be quite a basic thing, but as a Python learner I've been struggling with it for hours. The documentation has not provided me with an answer so far.
The problem is that an import statement included in a module does not seem to be executed when I import this module from a python script. What I have is as follows:
I have a file project.py (i.e. python library) that looks like this:
import datetime
class Project:
""" This class is a container for project data """
title = ""
manager = ""
date = datetime.datetime.min
def __init__( self, title="", manager="", date=datetime.datetime.min ):
""" Init function with some defaults """
self.title = title
self.manager = manager
self.date = date
This library is later used in a script (file.py) that imports project, it starts like this:
import project
print datetime.datetime.min
The problem then arises when I try to execute this script with Python file.py. Python then complains with the folliwing NameError:
Traceback (most recent call last):
File "file.py", line 3, in <module>
print datetime.datetime.min
NameError: name 'datetime' is not defined
This actually happens also if I try to make the same statements (import and print) directly from the Python shell.
Shouldn't the datetime module be automatically imported in the precise moment that I call import project?
Thanks a lot in advance.
The datetime module is only imported into the project namespace. So you could access it as project.datetime.datetime.min, but really you should import it into your script directly.
Every symbol (name) that you create in your project.py file (like your Project class) ends up in the project namespace, which includes things you import from other modules. This isn't as inefficient as it might seem however - the actual datetime module is still only imported once, no matter how many times you do it. Every time you import it subsequent to the first one it's just importing the names into the current namespace, but not actually doing all the heavy lifting of reading and importing the module.
Try thinking of the import statement as roughly equivalent to:
project = __import__('project')
Effectively an import statement is simply an assignment to a variable. There may be some side effects as the module is loaded, but from inside your script all you see is a simple assignment to a name.
You can pull in all the names from a module using from project import *, but don't do that because it makes your code much more brittle and harder to maintain. Instead either just import the module or exactly the names you want.
So for your code something like:
import datetime
from project import Project
is the sort of thing you should be doing.

Python - import error

I've done what I shouldn't have done and written 4 modules (6 hours or so) without running any tests along the way.
I have a method inside of /mydir/__init__.py called get_hash(), and a class inside of /mydir/utils.py called SpamClass.
/mydir/utils.py imports get_hash() from /mydir/__init__.
/mydir/__init__.py imports SpamClass from /mydir/utils.py.
Both the class and the method work fine on their own but for some reason if I try to import /mydir/, I get an import error saying "Cannot import name get_hash" from /mydir/__init__.py.
The only stack trace is the line saying that __init__.py imported SpamClass. The next line is where the error occurs in in SpamClass when trying to import get_hash. Why is this?
This is a pretty easy problem to encounter. What's happening is this that the interpreter evaluates your __init__.py file line-by line. When you have the following code:
import mydir.utils
def get_hash(): return 1
The interpreter will suspend processing __init__.py at the point of import mydir.utils until it has fully executed 'mydir/utils.py' So when utils.py attempts to import get_hash(), it isn't defined because the interpreter hasn't gotten to it's definition yet.
To add to what the others have said, another good approach to avoiding circular import problems is to avoid from module import stuff.
If you just do standard import module at the top of each script, and write module.stuff in your functions, then by the time those functions run, the import will have finished and the module members will all be available.
You then also don't have to worry about situations where some modules can update/change one of their members (or have it monkey-patched by a naughty third party). If you'd imported from the module, you'd still have your old, out-of-date copy of the member.
Personally, I only use from-import for simple, dependency-free members that I'm likely to refer to a lot: in particular, symbolic constants.
In absence of more information, I would say you have a circular import that you aren't working around. The simplest, most obvious fix is to not put anything in mydir/__init__.py that you want to use from any module inside mydir. So, move your get_hash function to another module inside the mydir package, and import that module where you need it.

Categories