Newbie here
I want to import a class from a file in another directory, in this case:
C:\Users\jose_\Desktop\my_ref\stack_class.py, using the from - import statement. I have an init.py file in said directory but cannot find the right sintax anywhere.
How do you put C:\Users\jose_\Desktop\my_ref\stack_class.py in the import part?
I have tried using these other two ways:
exec(open("file path on windows").read())
and the import sys and sys.path.insert
they both work, trying to do it with the import statement.
from C:\Users\jose_\Desktop\my_ref\stack_class.py import Stack #Error here
foo = Stack()
print(type(foo))
Error
File "C:/Users/jose_/OneDrive/Mis_Documentos/Educacion/Linkedin/Ex_Files_Python_Data_Structures_Queues/Exercise_Files/Ch02/02_02/End/main2.py", line 4
from C:\Users\jose_\Desktop\my_ref\stack_class.py import Stack
^
SyntaxError: invalid syntax
As far as I know, you cannot import from a file path in Python.
You can only import by passing a module name:
import module.submodule
# then
module.submodule.sth()
or
from module.submodule import sth
# then
sth()
And Python will search module/submodule.py and module/submodule/__init_.py in all the directories in sys.path.
So if you want to import from a file in another directory created by yourself (not included in the sys.path list) you have to append that directory to the list to tell Python where to find that module. Try to run:
import sys
sys.path.append('C:\\Users\\jose_\\Desktop\\my_ref')
from stack_class import Stack
# then
foo = Stack()
print(type(foo))
Edit
If you don't want to append to sys.path, you need to move your module to one of the diretories in sys.path, for example, the current directory . is also in sys.path, or Python won't know where the module is (C:\ is not in sys.path).
Python never imports from directories that are not included in sys.path (via import statements, I mean)!
Did you make sure to switch your forward slashes "\" with back slashes "/" ?
try using:
sys.path.extend('file path here')
to add the folder path to your python path, that way python knows where to look for the stack_class module - either that or navigate to the folder before importing
also make sure in the folder your init file is called __init__.py
you should then be able to do
from stack_class import Stack
Related
I'm trying run an env_setup script that imports modules used in my main_script. But despite successfully running env_setup.py the modules are not being imported (presumably it is being run in its own environment).
Previously I know I have somehow sucesfully used:
from env_setup import *
However this fails for me now.
I tried a second approach using:
importlib.util.spec_from_file_location(name, location)
But this also fails.
Below is an example of what I am attempting (using the second approach in my main_script.py):
Example env_setup.py script:
import datetime # import module
print("modules imported!!!") # confirm import
Example main_script.py script:
# This first section should import `datetime` using `env_setup.py`
import importlib
spec = importlib.util.spec_from_file_location(
name='setup',
location='/home/solebay/my project/env_setup.py' # path to `set_up` script
)
my_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(my_mod)
# This returns "modules imported!!!"
# Here we run a basic command to check if `datetime` was imported...
now = datetime.datetime.now()
print(now.strftime('%H:%M:%S on %A, %B the %dth, %Y')) # Should print time/date
# NameError: name 'datetime' is not defined
How do I get python to actually import the required modules into the environment running main_script.py? It creates a __pycache__ folder so I know the path is correct.
After dynamically importing a module you can either access the module directly by using my_mod.function() or import everything (imitate from module import *) like so:
import sys
sys.modules["setup"] = my_mod
from setup import *
del sys.modules["setup"] # Optional
After lots of searching I decided:
from env_setup import *
Should absolutely work.
I moved my most recent scripts to a fresh directory with a simpler tree and everything works.
I'm thinking it was a bug?
Update (Not a bug):
As per the useful suggestion of Bharel I ran..
import os
os.getcwd() # Returned 'wrong' directory
os.listdir() # Returned 'wrong' listing
Visual inspection of the folder tree showed that env_setup.py was present, but this file and others were absent from the true listing returned by os.listdir().
I'm running my code through the IDE "Atom" using the "Hydrogen" module. I opened a new window, added a new project folder and ran the command again and it updated.
I'm assuming I moved a folder and Atom didn't have a chance to update the path.
End result:
from env_setup import *
Works prefectly.
In python 2 I can create a module like this:
parent
->module
->__init__.py (init calls 'from file import ClassName')
file.py
->class ClassName(obj)
And this works. In python 3 I can do the same thing from the command interpreter and it works (edit: This worked because I was in the same directory running the interpreter). However if I create __ init __.py and do the same thing like this:
"""__init__.py"""
from file import ClassName
"""file.py"""
class ClassName(object): ...etc etc
I get ImportError: cannot import name 'ClassName', it doesn't see 'file' at all. It will do this as soon as I import the module even though I can import everything by referencing it directly (which I don't want to do as it's completely inconsistent with the rest of our codebase). What gives?
In python 3 all imports are absolute unless a relative path is given to perform the import from. You will either need to use an absolute or relative import.
Absolute import:
from parent.file import ClassName
Relative import:
from . file import ClassName
# look for the module file in same directory as the current module
Try import it this way:
from .file import ClassName
See here more info on "Guido's decision" on imports in python 3 and complete example on how to import in python 3.
I have a python project with this structure: (This is not a real project, only for testing)
ImportTest
ImportPersonsTest\
ImportPerson\
ImportPerson.py
RunImportPersonTest.py
RunImportTests.py
I want this tests to call each other. E.g :
RunImportTests.py calls a method in RunImportPersonTest.py, and RunImportPersonTest.py calls a method ImportPerson.py
RunImportPersonTest:
import os
import sys
sys.path.insert(0, os.getcwd() + "../../../")
from ImportPerson import ImportPerson
RunImportTests
import os
import sys
sys.path.insert(0, os.getcwd() + "../../")
from ImportPersonsTest import RunImportsPersonTest
I have success when I run ImportPerson.py and RunImportPersonTest.py, but when I try to run RunImportTests I get this error :
Traceback (most recent call last):
File "xxx\LiClipse Workspace\SystemTest\ImportTest\RunImportTests.py", line 4, in <module>
from ImportPersonsTest import RunImportsPersonTest
File "xxx\LiClipse Workspace\SystemTest\ImportTest\ImportPersonsTest\RunImportsPersonTest.py", line 4, in <module>
from ImportPerson import ImportPerson
ImportError: No module named 'ImportPerson'
Any suggestions?
Edit
New Structure
ImportTest
ImportPersonsTest\
ImportPerson\
ImportPerson.py
__init__.py
RunImportPersonTest.py
__init__.py
RunImportTests.py
__init__.py
Looks like you don't have any __init__.py files in your project. Python needs those files to be able to import modules from folders. The good news is, they are very easy to make: most of the time, they don't need anything in them, they just have to exist.
See: https://docs.python.org/2/tutorial/modules.html#packages
I think your use of os.getcwd() is flawed.
My guess is that you're running your program from the ImportTest directory and so your current working directory will already allow you to do the first import without any need to fix up your path. When you then try the second import, adding ".../ImportTest/../../.." or ".../ImportTest/../.." isn't helping Python find it.
To fix it either add the ImportPersonsTest directory to your path or use a suitably modified name in the import (ensuring you have your init files as already flagged) - e.g.
from ImportPersonsTest.ImportPerson import ImportPerson
There is two basic problem:
os.getcwd() as other os functions return path with no separator at the end. In fact you insert xxx\LiClipse Workspace\SystemTest\ImportTest../../../ which is not a valid path
As mention by #peter, using os.getcwd() is bad idea - it's depend on your location when you run the script. Use:
sys.path.append(os.path.dirname(__file__)) (insert recommend only at special cases)
But,
It seems that none of this caused your problem. It's only insert bad stuff to your sys.path. Your importing need to work good cause all the importing done from the self-module-dir, where python firstly search for the requested module.
I copy your package to mine machine - and both runs well!
I fix one spelling bug (RunImportsPersonTest -- RunImportPersonTest) - maybe there is other spelling problem
Assuming my directory structure is:
C:\Scripts\myscript.py
C:\Scripts\customjson\json.py
The myscript.py python script has at the top:
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'customjson'))
import json
The thing is, I have a "customjson" folder that contains a json.py that I want to use instead of the default json package that Python 2.7 comes with. How do I make it so that the script uses "customjson" instead of the standard json?
Try to insert your customjson directory first in sys.path:
sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'customjson'))
import json
You could use something like this:
import sys
_orig_path = sys.path
sys.path = ["C:\Scripts\customjson"]
import json
sys.path = _orig_path
But, of course, that code wouldn't be portable. To make it portable, you could use:
import sys, os
_orig_path = sys.path
sys.path = [
os.path.abspath(os.path.join(os.path.dirname(__file__), "customjson")),
]
import json
sys.path = _orig_path
Or, you could rename json.py to, for example, json2.py. And then import it:
import json2
or, if you absolutely need it to be named json:
import json2 as json
..yeah, the second one looks better, doesn't it?
I say: Make your customjson folder a package.
It's easy:
Create a file named __init__.py in your customjson folder. The file can be empty if you don't want anything special defined at the package level.
Change your import statement to refer to the module within the package (i.e. import customjson.json).
Change your references to the module to use the full path (customjson.json.whatever), or instead further change your import statement to include as as clause (import customjson.json as json). If you're using from ... import ... syntax, this is unnecessary. While using an as clause may be easier than rewriting your accesses, it may confusing any other programmer who reads your code and expects it to be using the standard json module.
Given the folder layout you describe in the question, you won't need to mess around with the module search path at all if you go this route, since the running script's current folder is always included in the path and that's where the customjson package is located.
What would be the best (read: cleanest) way to tell Python to import all modules from some folder?
I want to allow people to put their "mods" (modules) in a folder in my app which my code should check on each startup and import any module put there.
I also don't want an extra scope added to the imported stuff (not "myfolder.mymodule.something", but "something")
If transforming the folder itself in a module, through the use of a __init__.py file and using from <foldername> import * suits you, you can iterate over the folder contents
with "os.listdir" or "glob.glob", and import each file ending in ".py" with the __import__ built-in function:
import os
for name in os.listdir("plugins"):
if name.endswith(".py"):
#strip the extension
module = name[:-3]
# set the module name in the current global name space:
globals()[module] = __import__(os.path.join("plugins", name)
The benefit of this approach is: it allows you to dynamically pass the module names to __import__ - while the ìmport statement needs the module names to be hardcoded, and it allows you to check other things about the files - maybe size, or if they import certain required modules, before importing them.
Create a file named
__init__.py
inside the folder and import the folder name like this:
>>> from <folder_name> import * #Try to avoid importing everything when you can
>>> from <folder_name> import module1,module2,module3 #And so on
You might want to try that project: https://gitlab.com/aurelien-lourot/importdir
With this module, you only need to write two lines to import all plugins from your directory and you don't need an extra __init__.py (or any other other extra file):
import importdir
importdir.do("plugins/", globals())