Import package within sub-package [duplicate] - python-2.7

Assume I have the following files,
pkg/
pkg/__init__.py
pkg/main.py # import string
pkg/string.py # print("Package's string module imported")
Now, if I run main.py, it says "Package's string module imported".
This makes sense and it works as per this statement in this link:
"it will first look in the package's directory"
Assume I modified the file structure slightly (added a core directory):
pkg/
pkg/__init__.py
plg/core/__init__.py
pkg/core/main.py # import string
pkg/string.py # print("Package's string module imported")
Now, if I run python core/main.py, it loads the built-in string module.
In the second case too, if it has to comply with the statement "it will first look in the package's directory" shouldn't it load the local string.py because pkg is the "package directory"?
My sense of the term "package directory" is specifically the root folder of a collection of folders with __init__.py. So in this case, pkg is the "package directory". It is applicable to main.py and also files in sub- directories like core/main.py because it is part of this "package".
Is this technically correct?
PS: What follows after # in the code snippet is the actual content of the file (with no leading spaces).

Packages are directories with a __init__.py file, yes, and are loaded as a module when found on the module search path. So pkg is only a package that you can import and treat as a package if the parent directory is on the module search path.
But by running the pkg/core/main.py file as a script, Python added the pkg/core directory to the module search path, not the parent directory of pkg. You do have a __init__.py file on your module search path now, but that's not what defines a package. You merely have a __main__ module, there is no package relationship to anything else, and you can't rely on implicit relative imports.
You have three options:
Do not run files inside packages as scripts. Put a script file outside of your package, and have that import your package as needed. You could put it next to the pkg directory, or make sure the pkg directory is first installed into a directory already on the module search path, or by having your script calculate the right path to add to sys.path.
Use the -m command line switch to run a module as if it is a script. If you use python -m pkg.core Python will look for a __main__.py file and run that as a script. The -m switch will add the current working directory to your module search path, so you can use that command when you are in the right working directory and everything will work. Or have your package installed in a directory already on the module search path.
Have your script add the right directory to the module search path (based on os.path.absolute(__file__) to get a path to the current file). Take into account that your script is always named __main__, and importing pkg.core.main would add a second, independent module object; you'd have two separate namespaces.
I also strongly advice against using implicit relative imports. You can easily mask top-level modules and packages by adding a nested package or module with the same name. pkg/time.py would be found before the standard-library time module if you tried to use import time inside the pkg package. Instead, use the Python 3 model of explicit relative module references; add from __future__ import absolute_import to all your files, and then use from . import <name> to be explicit as to where your module is being imported from.

Related

Python 2.7 Unable to import python file as a package [duplicate]

I've been here:
http://www.python.org/dev/peps/pep-0328/
http://docs.python.org/2/tutorial/modules.html#packages
Python packages: relative imports
python relative import example code does not work
Relative imports in python 2.5
Relative imports in Python
Python: Disabling relative import
and plenty of URLs that I did not copy, some on SO, some on other sites, back when I thought I'd have the solution quickly.
The forever-recurring question is this: how do I solve this "Attempted relative import in non-package" message?
ImportError: attempted relative import with no known parent package
I built an exact replica of the package on pep-0328:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
The imports were done from the console.
I did make functions named spam and eggs in their appropriate modules. Naturally, it didn't work. The answer is apparently in the 4th URL I listed, but it's all alumni to me. There was this response on one of the URLs I visited:
Relative imports use a module's name attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to 'main') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
The above response looks promising, but it's all hieroglyphs to me. So my question, how do I make Python not return to me "Attempted relative import in non-package"? has an answer that involves -m, supposedly.
Can somebody please tell me why Python gives that error message, what it means by "non-package", why and how do you define a 'package', and the precise answer put in terms easy enough for a kindergartener to understand.
Script vs. Module
Here's an explanation. The short version is that there is a big difference between directly running a Python file, and importing that file from somewhere else. Just knowing what directory a file is in does not determine what package Python thinks it is in. That depends, additionally, on how you load the file into Python (by running or by importing).
There are two ways to load a Python file: as the top-level script, or as a
module. A file is loaded as the top-level script if you execute it directly, for instance by typing python myfile.py on the command line. It is loaded as a module when an import statement is encountered inside some other file. There can only be one top-level script at a time; the top-level script is the Python file you ran to start things off.
Naming
When a file is loaded, it is given a name (which is stored in its __name__ attribute).
If it was loaded as the top-level script, its name is __main__.
If it was loaded as a module, its name is [ the filename, preceded by the names of any packages/subpackages of which it is a part, separated by dots ], for example, package.subpackage1.moduleX.
But be aware, if you load moduleX as a module from shell command line using something like python -m package.subpackage1.moduleX, the __name__ will still be __main__.
So for instance in your example:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
if you imported moduleX (note: imported, not directly executed), its name would be package.subpackage1.moduleX. If you imported moduleA, its name would be package.moduleA. However, if you directly run moduleX from the command line, its name will instead be __main__, and if you directly run moduleA from the command line, its name will be __main__. When a module is run as the top-level script, it loses its normal name and its name is instead __main__.
Accessing a module NOT through its containing package
There is an additional wrinkle: the module's name depends on whether it was imported "directly" from the directory it is in or imported via a package. This only makes a difference if you run Python in a directory, and try to import a file in that same directory (or a subdirectory of it). For instance, if you start the Python interpreter in the directory package/subpackage1 and then do import moduleX, the name of moduleX will just be moduleX, and not package.subpackage1.moduleX. This is because Python adds the current directory to its search path when the interpreter is entered interactively; if it finds the to-be-imported module in the current directory, it will not know that that directory is part of a package, and the package information will not become part of the module's name.
A special case is if you run the interpreter interactively (e.g., just type python and start entering Python code on the fly). In this case, the name of that interactive session is __main__.
Now here is the crucial thing for your error message: if a module's name has no dots, it is not considered to be part of a package. It doesn't matter where the file actually is on disk. All that matters is what its name is, and its name depends on how you loaded it.
Now look at the quote you included in your question:
Relative imports use a module's name attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to 'main') then relative imports are resolved as if the module were a top-level module, regardless of where the module is actually located on the file system.
Relative imports...
Relative imports use the module's name to determine where it is in a package. When you use a relative import like from .. import foo, the dots indicate to step up some number of levels in the package hierarchy. For instance, if your current module's name is package.subpackage1.moduleX, then ..moduleA would mean package.moduleA. For a from .. import to work, the module's name must have at least as many dots as there are in the import statement.
... are only relative in a package
However, if your module's name is __main__, it is not considered to be in a package. Its name has no dots, and therefore you cannot use from .. import statements inside it. If you try to do so, you will get the "relative-import in non-package" error.
Scripts can't import relative
What you probably did is you tried to run moduleX or the like from the command line. When you did this, its name was set to __main__, which means that relative imports within it will fail, because its name does not reveal that it is in a package. Note that this will also happen if you run Python from the same directory where a module is, and then try to import that module, because, as described above, Python will find the module in the current directory "too early" without realizing it is part of a package.
Also remember that when you run the interactive interpreter, the "name" of that interactive session is always __main__. Thus you cannot do relative imports directly from an interactive session. Relative imports are only for use within module files.
Two solutions:
If you really do want to run moduleX directly, but you still want it to be considered part of a package, you can do python -m package.subpackage1.moduleX. The -m tells Python to load it as a module, not as the top-level script.
Or perhaps you don't actually want to run moduleX, you just want to run some other script, say myfile.py, that uses functions inside moduleX. If that is the case, put myfile.py somewhere else – not inside the package directory – and run it. If inside myfile.py you do things like from package.moduleA import spam, it will work fine.
Notes
For either of these solutions, the package directory (package in your example) must be accessible from the Python module search path (sys.path). If it is not, you will not be able to use anything in the package reliably at all.
Since Python 2.6, the module's "name" for package-resolution purposes is determined not just by its __name__ attributes but also by the __package__ attribute. That's why I'm avoiding using the explicit symbol __name__ to refer to the module's "name". Since Python 2.6 a module's "name" is effectively __package__ + '.' + __name__, or just __name__ if __package__ is None.)
This is really a problem within python. The origin of confusion is that people mistakenly takes the relative import as path relative which is not.
For example when you write in faa.py:
from .. import foo
This has a meaning only if faa.py was identified and loaded by python, during execution, as a part of a package. In that case,the module's name
for faa.py would be for example some_packagename.faa. If the file was loaded just because it is in the current directory, when python is run, then its name would not refer to any package and eventually relative import would fail.
A simple solution to refer modules in the current directory, is to use this:
if __package__ is None or __package__ == '':
# uses current directory visibility
import foo
else:
# uses current package visibility
from . import foo
There are too much too long anwers in a foreign language. So I'll try to make it short.
If you write from . import module, opposite to what you think, module will not be imported from current directory, but from the top level of your package! If you run .py file as a script, it simply doesn't know where the top level is and thus refuses to work.
If you start it like this py -m package.module from the directory above package, then python knows where the top level is. That's very similar to java: java -cp bin_directory package.class
So after carping about this along with many others, I came across a note posted by Dorian B in this article that solved the specific problem I was having where I would develop modules and classes for use with a web service, but I also want to be able to test them as I'm coding, using the debugger facilities in PyCharm. To run tests in a self-contained class, I would include the following at the end of my class file:
if __name__ == '__main__':
# run test code here...
but if I wanted to import other classes or modules in the same folder, I would then have to change all my import statements from relative notation to local references (i.e. remove the dot (.)) But after reading Dorian's suggestion, I tried his 'one-liner' and it worked! I can now test in PyCharm and leave my test code in place when I use the class in another class under test, or when I use it in my web service!
# import any site-lib modules first, then...
import sys
parent_module = sys.modules['.'.join(__name__.split('.')[:-1]) or '__main__']
if __name__ == '__main__' or parent_module.__name__ == '__main__':
from codex import Codex # these are in same folder as module under test!
from dblogger import DbLogger
else:
from .codex import Codex
from .dblogger import DbLogger
The if statement checks to see if we're running this module as main or if it's being used in another module that's being tested as main. Perhaps this is obvious, but I offer this note here in case anyone else frustrated by the relative import issues above can make use of it.
Here's a general recipe, modified to fit as an example, that I am using right now for dealing with Python libraries written as packages, that contain interdependent files, where I want to be able to test parts of them piecemeal. Let's call this lib.foo and say that it needs access to lib.fileA for functions f1 and f2, and lib.fileB for class Class3.
I have included a few print calls to help illustrate how this works. In practice you would want to remove them (and maybe also the from __future__ import print_function line).
This particular example is too simple to show when we really need to insert an entry into sys.path. (See Lars' answer for a case where we do need it, when we have two or more levels of package directories, and then we use os.path.dirname(os.path.dirname(__file__))—but it doesn't really hurt here either.) It's also safe enough to do this without the if _i in sys.path test. However, if each imported file inserts the same path—for instance, if both fileA and fileB want to import utilities from the package—this clutters up sys.path with the same path many times, so it's nice to have the if _i not in sys.path in the boilerplate.
from __future__ import print_function # only when showing how this works
if __package__:
print('Package named {!r}; __name__ is {!r}'.format(__package__, __name__))
from .fileA import f1, f2
from .fileB import Class3
else:
print('Not a package; __name__ is {!r}'.format(__name__))
# these next steps should be used only with care and if needed
# (remove the sys.path manipulation for simple cases!)
import os, sys
_i = os.path.dirname(os.path.abspath(__file__))
if _i not in sys.path:
print('inserting {!r} into sys.path'.format(_i))
sys.path.insert(0, _i)
else:
print('{!r} is already in sys.path'.format(_i))
del _i # clean up global name space
from fileA import f1, f2
from fileB import Class3
... all the code as usual ...
if __name__ == '__main__':
import doctest, sys
ret = doctest.testmod()
sys.exit(0 if ret.failed == 0 else 1)
The idea here is this (and note that these all function the same across python2.7 and python 3.x):
If run as import lib or from lib import foo as a regular package import from ordinary code, __package is lib and __name__ is lib.foo. We take the first code path, importing from .fileA, etc.
If run as python lib/foo.py, __package__ will be None and __name__ will be __main__.
We take the second code path. The lib directory will already be in sys.path so there is no need to add it. We import from fileA, etc.
If run within the lib directory as python foo.py, the behavior is the same as for case 2.
If run within the lib directory as python -m foo, the behavior is similar to cases 2 and 3. However, the path to the lib directory is not in sys.path, so we add it before importing. The same applies if we run Python and then import foo.
(Since . is in sys.path, we don't really need to add the absolute version of the path here. This is where a deeper package nesting structure, where we want to do from ..otherlib.fileC import ..., makes a difference. If you're not doing this, you can omit all the sys.path manipulation entirely.)
Notes
There is still a quirk. If you run this whole thing from outside:
$ python2 lib.foo
or:
$ python3 lib.foo
the behavior depends on the contents of lib/__init__.py. If that exists and is empty, all is well:
Package named 'lib'; __name__ is '__main__'
But if lib/__init__.py itself imports routine so that it can export routine.name directly as lib.name, you get:
$ python2 lib.foo
Package named 'lib'; __name__ is 'lib.foo'
Package named 'lib'; __name__ is '__main__'
That is, the module gets imported twice, once via the package and then again as __main__ so that it runs your main code. Python 3.6 and later warn about this:
$ python3 lib.routine
Package named 'lib'; __name__ is 'lib.foo'
[...]/runpy.py:125: RuntimeWarning: 'lib.foo' found in sys.modules
after import of package 'lib', but prior to execution of 'lib.foo';
this may result in unpredictable behaviour
warn(RuntimeWarning(msg))
Package named 'lib'; __name__ is '__main__'
The warning is new, but the warned-about behavior is not. It is part of what some call the double import trap. (For additional details see issue 27487.) Nick Coghlan says:
This next trap exists in all current versions of Python, including 3.3, and can be summed up in the following general guideline: "Never add a package directory, or any directory inside a package, directly to the Python path".
Note that while we violate that rule here, we do it only when the file being loaded is not being loaded as part of a package, and our modification is specifically designed to allow us to access other files in that package. (And, as I noted, we probably shouldn't do this at all for single level packages.) If we wanted to be extra-clean, we might rewrite this as, e.g.:
import os, sys
_i = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if _i not in sys.path:
sys.path.insert(0, _i)
else:
_i = None
from sub.fileA import f1, f2
from sub.fileB import Class3
if _i:
sys.path.remove(_i)
del _i
That is, we modify sys.path long enough to achieve our imports, then put it back the way it was (deleting one copy of _i if and only if we added one copy of _i).
Here is one solution that I would not recommend, but might be useful in some situations where modules were simply not generated:
import os
import sys
parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir_name + "/your_dir")
import your_script
your_script.a_function()
#BrenBarn's answer says it all, but if you're like me it might take a while to understand. Here's my case and how #BrenBarn's answer applies to it, perhaps it will help you.
The case
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
Using our familiar example, and add to it that moduleX.py has a relative import to ..moduleA. Given that I tried writing a test script in the subpackage1 directory that imported moduleX, but then got the dreaded error described by the OP.
Solution
Move test script to the same level as package and import package.subpackage1.moduleX
Explanation
As explained, relative imports are made relative to the current name. When my test script imports moduleX from the same directory, then module name inside moduleX is moduleX. When it encounters a relative import the interpreter can't back up the package hierarchy because it's already at the top
When I import moduleX from above, then name inside moduleX is package.subpackage1.moduleX and the relative import can be found
Following up on what Lars has suggested I've wrapped this approach in an experimental, new import library: ultraimport
It gives the programmer more control over imports and it allows file system based imports. Therefore, you can do relative imports from scripts. Parent package not necessary. ultraimports will always work, no matter how you run your code or what is your current working directory because ultraimport makes imports unambiguous. You don't need to change sys.path and also you don't need a try/except block to sometimes do relative imports and sometimes absolute.
You would then write in somefile.py something like:
import ultraimport
foo = ultraimport('__dir__/foo.py')
__dir__ is the directory of somefile.py, the caller of ultraimport(). foo.py would live in the same directory as somefile.py.
One caveat when importing scripts like this is if they contain further relative imports. ultraimport has a builtin preprocessor to rewrite subsequent relative imports to ultraimports so they continue to work. Though, this is currently somewhat limited as original Python imports are ambiguous and there's only so much you can do about it.
I had a similar problem where I didn't want to change the Python module search
path and needed to load a module relatively from a script (in spite of "scripts can't import relative with all" as BrenBarn explained nicely above).
So I used the following hack. Unfortunately, it relies on the imp module that
became deprecated since version 3.4 to be dropped in favour of importlib.
(Is this possible with importlib, too? I don't know.) Still, the hack works for now.
Example for accessing members of moduleX in subpackage1 from a script residing in the subpackage2 folder:
#!/usr/bin/env python3
import inspect
import imp
import os
def get_script_dir(follow_symlinks=True):
"""
Return directory of code defining this very function.
Should work from a module as well as from a script.
"""
script_path = inspect.getabsfile(get_script_dir)
if follow_symlinks:
script_path = os.path.realpath(script_path)
return os.path.dirname(script_path)
# loading the module (hack, relying on deprecated imp-module)
PARENT_PATH = os.path.dirname(get_script_dir())
(x_file, x_path, x_desc) = imp.find_module('moduleX', [PARENT_PATH+'/'+'subpackage1'])
module_x = imp.load_module('subpackage1.moduleX', x_file, x_path, x_desc)
# importing a function and a value
function = module_x.my_function
VALUE = module_x.MY_CONST
A cleaner approach seems to be to modify the sys.path used for loading modules as mentioned by Federico.
#!/usr/bin/env python3
if __name__ == '__main__' and __package__ is None:
from os import sys, path
# __file__ should be defined in this case
PARENT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
sys.path.append(PARENT_DIR)
from subpackage1.moduleX import *
__name__ changes depending on whether the code in question is run in the global namespace or as part of an imported module.
If the code is not running in the global space, __name__ will be the name of the module. If it is running in global namespace -- for example, if you type it into a console, or run the module as a script using python.exe yourscriptnamehere.py then __name__ becomes "__main__".
You'll see a lot of python code with if __name__ == '__main__' is used to test whether the code is being run from the global namespace – that allows you to have a module that doubles as a script.
Did you try to do these imports from the console?
Relative imports use a module's name attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to 'main') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
Wrote a little python package to PyPi that might help viewers of this question. The package acts as workaround if one wishes to be able to run python files containing imports containing upper level packages from within a package / project without being directly in the importing file's directory. https://pypi.org/project/import-anywhere/
In most cases when I see the ValueError: attempted relative import beyond top-level package and pull my hair out, the solution is as follows:
You need to step one level higher in the file hierarchy!
#dir/package/module1/foo.py
#dir/package/module2/bar.py
from ..module1 import foo
Importing bar.py when interpreter is started in dir/package/ will result in error despite the import process never going beyond your current directory.
Importing bar.py when interpreter is started in dir/ will succeed.
Similarly for unit tests:
python3 -m unittest discover --start-directory=. successfully works from dir/, but not from dir/package/.

Do I need to update the path when installing a module?

So I'm trying to install a module, specifically xlutils. I've read through the resources that I've linked at the bottom, but none of those resources have allowed me to successfully install and import the module. I'm running Windows 8 and using Python 2.7.
I downloaded the .tar.gz file containing xlutils, and unpacked it to C:\Python which was then a .tar file, so I unpacked that to the same folder. This created a folder, xlutils, which looked like it contained what I need. I also read somewhere that these should be stored in site-packages, so I moved it there.
But when I run import commands, they don't work, just tell me the module couldn't be found. When I look at the path browser, it doesn't see the folder, but I'm certain it's in there. That leads me to wonder, do I need to do something to manually update what the path browser can view?
Note that I've also already tried going to the command line, navigating to the folder containing the module, and typing python setup.py install but that just tells me that the term "python" is not found. In general, my command line always does this though. Usually I have to type .\python instead to run Python from the command line, but I also tried doing that here (i.e navigating to the folder and typing .\python setup.py install but it still says the same thing).
Also note that I can import numpy and scipy just fine, and I can see them in the path browser--not sure why those work while this one doesn't.
Resources I've already read but hasn't solved my problem:
(... Well, I tried providing the resources I've already viewed, but can't so many links with such low reputation. But basically, I've read the first ten links on a Google search and two or three past Stack questions and answers.)
Solutions I see:
You can use the absolute path C:\Python27\python.exe setup.py install
You can add the Python directory C:\Python27\ to your path variable before running python setup.py install

ImportError: No module named for my code on Readthedocs

I am trying to link my Sphinx documentation with ReadtheDocs. I can build the documentation locally but when I try to have ReadtheDocs automatically generate the documentation I get the following error:
Sphinx Standard Error
Making output directory...
Exception occurred:
File "/var/build/user_builds/mousedb/checkouts/latest/Docs/source/conf.py", line 25, in <module>
from mousedb import settings
ImportError: No module named mousedb
The full traceback has been saved in /tmp/sphinx-err-n_8fkR.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
Either send bugs to the mailing list at <http://groups.google.com/group/sphinx-dev/>,
or report them in the tracker at <http://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!
My project name is mousedb. I don't understand why I get this import error in the auto-build but not locally.
Update
Based on the comments I think that this is an issue for importing my settings file into a sibling Docs directory. Rather than doing an absolute import (as I had been doing) I should be doing a relative import based on the location of settings.py and conf.py.
I want to import my settings file into my conf.py with the following directory structure:
-mousedb
--settings.py
-Docs
--source
---conf.py
--build
You originally talked about a "local absolute path to my code" and now about setting up relative paths to your code. This probably means you're not using a setup.py file and also not a virtualenv.
In the same directory as Docs/ and mousedb/, add a setup.py:
from setuptools import setup
setup(name='mousedb',
version='0.1',
description="My sample package",
long_description="",
author='TODO',
author_email='todo#example.org',
license='TODO',
packages=['mousedb'],
zip_safe=False,
install_requires=[
'Django',
# 'Sphinx',
# ^^^ Not sure if this is needed on readthedocs.org
# 'something else?',
],
)
After committing/pushing/whatever this file, you can go to your readthedocs settings for your project. Enable the "use virtualenv" setting. This will "nstall your project inside a virtualenv using setup.py install".
The end result is that everything python-related that readthedocs does will have your project in it's sys.path.
The probable cause of your problems is that you run sphinx from within your "root" directory on your local system, where python magically finds the mousedb/ package in your current directory. But readthedocs apparently runs it from within the Docs/ directory and thus cannot find mousedb.

Go build: "Cannot find package" (even though GOPATH is set)

Even though I have GOPATH properly set, I still can't get "go build" or "go run" to find my own packages. What am I doing wrong?
$ echo $GOROOT
/usr/local/go
$ echo $GOPATH
/home/mitchell/go
$ cat ~/main.go
package main
import "foobar"
func main() { }
$ cat /home/mitchell/go/src/foobar.go
package foobar
$ go build main.go
main.go:3:8: import "foobar": cannot find package
It does not work because your foobar.go source file is not in a directory called foobar. go build and go install try to match directories, not source files.
Set $GOPATH to a valid directory, e.g. export GOPATH="$HOME/go"
Move foobar.go to $GOPATH/src/foobar/foobar.go and building should work just fine.
Additional recommended steps:
Add $GOPATH/bin to your $PATH by: PATH="$GOPATH/bin:$PATH"
Move main.go to a subfolder of $GOPATH/src, e.g. $GOPATH/src/test
go install test should now create an executable in $GOPATH/bin that can be called by typing test into your terminal.
Although the accepted answer is still correct about needing to match directories with package names, you really need to migrate to using Go modules instead of using GOPATH. New users who encounter this problem may be confused about the mentions of using GOPATH (as was I), which are now outdated. So, I will try to clear up this issue and provide guidance associated with preventing this issue when using Go modules.
If you're already familiar with Go modules and are experiencing this issue, skip down to my more specific sections below that cover some of the Go conventions that are easy to overlook or forget.
This guide teaches about Go modules: https://golang.org/doc/code.html
Project organization with Go modules
Once you migrate to Go modules, as mentioned in that article, organize the project code as described:
A repository contains one or more modules. A module is a collection of
related Go packages that are released together. A Go repository
typically contains only one module, located at the root of the
repository. A file named go.mod there declares the module path: the
import path prefix for all packages within the module. The module
contains the packages in the directory containing its go.mod file as
well as subdirectories of that directory, up to the next subdirectory
containing another go.mod file (if any).
Each module's path not only serves as an import path prefix for its
packages, but also indicates where the go command should look to
download it. For example, in order to download the module
golang.org/x/tools, the go command would consult the repository
indicated by https://golang.org/x/tools (described more here).
An import path is a string used to import a package. A package's
import path is its module path joined with its subdirectory within the
module. For example, the module github.com/google/go-cmp contains a
package in the directory cmp/. That package's import path is
github.com/google/go-cmp/cmp. Packages in the standard library do not
have a module path prefix.
You can initialize your module like this:
$ go mod init github.com/mitchell/foo-app
Your code doesn't need to be located on github.com for it to build. However, it's a best practice to structure your modules as if they will eventually be published.
Understanding what happens when trying to get a package
There's a great article here that talks about what happens when you try to get a package or module: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
It discusses where the package is stored and will help you understand why you might be getting this error if you're already using Go modules.
Ensure the imported function has been exported
Note that if you're having trouble accessing a function from another file, you need to ensure that you've exported your function. As described in the first link I provided, a function must begin with an upper-case letter to be exported and made available for importing into other packages.
Names of directories
Another critical detail (as was mentioned in the accepted answer) is that names of directories are what define the names of your packages. (Your package names need to match their directory names.) You can see examples of this here: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
With that said, the file containing your main method (i.e., the entry point of your application) is sort of exempt from this requirement.
As an example, I had problems with my imports when using a structure like this:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
I was unable to import the code in utils into my main package.
However, once I put main.go into its own subdirectory, as shown below, my imports worked just fine:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
In that example, my go.mod file looks like this:
module git.mydomain.com/path/to/repo/my-app
go 1.14
When I saved main.go after adding a reference to utils.MyFunction(), my IDE automatically pulled in the reference to my package like this:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(I'm using VS Code with the Golang extension.)
Notice that the import path included the subdirectory to the package.
Dealing with a private repo
If the code is part of a private repo, you need to run a git command to enable access. Otherwise, you can encounter other errors This article mentions how to do that for private Github, BitBucket, and GitLab repos: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git-repositories-dfe795068db4
This issue is also discussed here: What's the proper way to "go get" a private repository?
I solved this problem by set my go env GO111MODULE to off
go env -w GO111MODULE=off
Note: setting GO111MODULE=off will turn off the latest GO Modules feature.
Reference: Why is GO111MODULE everywhere, and everything about Go Modules (updated with Go 1.17)
GO111MODULE with Go 1.16
As of Go 1.16, the default behavior is GO111MODULE=on, meaning that if
you want to keep using the old GOPATH way, you will have to force Go
not to use the Go Modules feature:
export GO111MODULE=off
In the recent go versions from 1.14 onwards, we have to do go mod vendor before building or running, since by default go appends -mod=vendor to the go commands.
So after doing go mod vendor, if we try to build, we won't face this issue.
Edit: since you meant GOPATH, see fasmat's answer (upvoted)
As mentioned in "How do I make go find my package?", you need to put a package xxx in a directory xxx.
See the Go language spec:
package math
A set of files sharing the same PackageName form the implementation of a package.
An implementation may require that all source files for a package inhabit the same directory.
The Code organization mentions:
When building a program that imports the package "widget" the go command looks for src/pkg/widget inside the Go root, and then—if the package source isn't found there—it searches for src/widget inside each workspace in order.
(a "workspace" is a path entry in your GOPATH: that variable can reference multiple paths for your 'src, bin, pkg' to be)
(Original answer)
You also should set GOPATH to ~/go, not GOROOT, as illustrated in "How to Write Go Code".
The Go path is used to resolve import statements. It is implemented by and documented in the go/build package.
The GOPATH environment variable lists places to look for Go code.
On Unix, the value is a colon-separated string.
On Windows, the value is a semicolon-separated string.
On Plan 9, the value is a list.
That is different from GOROOT:
The Go binary distributions assume they will be installed in /usr/local/go (or c:\Go under Windows), but it is possible to install them in a different location.
If you do this, you will need to set the GOROOT environment variable to that directory when using the Go tools.
TL;DR: Follow Go conventions! (lesson learned the hard way), check for old go versions and remove them. Install latest.
For me the solution was different. I worked on a shared Linux server and after verifying my GOPATH and other environment variables several times it still didn't work. I encountered several errors including 'Cannot find package' and 'unrecognized import path'. After trying to reinstall with this solution by the instructions on golang.org (including the uninstall part) still encountered problems.
Took me some time to realize that there's still an old version that hasn't been uninstalled (running go version then which go again... DAHH) which got me to this question and finally solved.
Running go env -w GO111MODULE=auto worked for me
Without editing GOPATH or anything, in my case just worked the following:
/app
├── main.go
├── /utils
└── utils.go
Import packages where needed. This can be unintuitive, because it isn't relative to the app path. You need to add the app in the package path too:
main.go:
package main
import(
"app/util"
)
Being in app directory, run:
go mod init app
go get <package/xxx>
go build main.go / go run main.go
You should be good to go.
GOPATH = /home/go
appPath = /home/projects/app
Create a proper go.mod and go.sum with go mod init app (delete old before)
After that resolve all dependencies like missing packages with go get github.com/example/package.
In simple words you can solve the import problem even with GO111MODULE=on with the following syntax for import:
import <your_module_name>/<package_name>
your_module_name -> module name which can be found in the go.mod file of the module as the first line.
example: github.com/nikhilg-hub/todo/ToDoBackend
package_name -> Path to your package within module.
example: orm
So the import statement would look like:
import "github.com/nikhilg-hub/todo/ToDoBackend/orm"
According to me we need to specify the module name + package name because we may need a same package name in two or more different modules.
Note: If you are importing a package from same module still you need to specify the full import path like above.
If you have a valid $GOROOT and $GOPATH but are developing outside of them, you might get this error if the package (yours or someone else's) hasn't been downloaded.
If that's the case, try go get -d (-d flag prevents installation) to ensure the package is downloaded before you run, build or install.
GOROOT should be set to your installation directory (/usr/local/go).
GOPATH should be set to your working directory (something like /home/username/project_folder).
GOPATH should not be set to GOROOT as your own project may need to install packages, and it's not recommended to have those packages in the Go installation folder. Check out this link for more.
For me none of the above solutions worked. But my go version was not the latest one. I have downloaded the latest version and replaced the older version in my mac os after that it worked perfectly.
I had a similar problem when building a docker file:
[1/3] STEP 9/9: RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
api/v1alpha1/XXX.go:5:2: cannot find package "." in:
/workspace/client/YYY/YYY.go
This only appeared when building the Dockerfile, building locally worked fine.
The problem turned out to be a missing statement in my Dockerfile:
COPY client/ client/
I do not understand why this happens, we must be able to import from wherever our file is in its nest, since I have discovered that if we have more than one nest this will throw an error.
package main
import (
"fmt"
"indexer/source/testPackage3" // this will be show a GOROOT error.
"indexer/testPackage"
"indexer/testPackage2"
)
func main() {
fmt.Println("Agile content indexer -")
fmt.Println(testPackage.Greeting())
fmt.Println(testPackage2.Greeting())
fmt.Println(testPackage3.Greeting())
}
├── testPackage2
│ ├── entry2.go
│ └── source
│ └── entry3.go
To conclude, I just want to tell you, the entry3.go file will not work when imported into my main file, which in this case is (main.go), I do not understand why, therefore, I have simply chosen to use a depth folder in the packages I need to export.
entry.go, entry2.go will work perfectly when imported, but entry3.go will not work..
In addition, both the directory and the name of the package must be the same so that they work properly when importing them.
Have you tried adding the absolute directory of go to your 'path'?
export PATH=$PATH:/directory/to/go/

What's the common way to layout a Django app with Buildout/djangorecipe?

I have a Django app that I've set up using Buildout laid out like so:
/workspace
/bin
/src
/myproject
settings.py
/myapp
views.py
...
bootstrap.py
buildout.cfg
setup.py
The issue is that I'd like both myproject.settings and myapp on the python path. I need the myproject.settings on the path so djangorecipe can import it. And I'd like myapp on the path so that I don't have to write import myproject.myapp all the time.
For now I've got both /workspace/src and /workspace/src/myproject in the Python path, but this feels like a hack and practically makes me worried if there might be situations where import some_module might have confusing resolution patterns because I have two directories that are parent-child to each other.
So questions are:
Is there an accepted way to lay this out?
Is it actually bad to have a directory and one of its sub-directories in the path?
There is no problem, on import some_module importer will search in each folder specified at sys.path for some_module/__init__.py and some_module.py. Same for import myproject.some_module, it will search for myproject module, then it will try to find in it some_module with same algorithm.
I'm using the same project structure.
If your buildout.cfg includes develop = . and whatever egg your setup.py defines is included as a dependency for your buildout/parts then whatever code path your setup.py defines will be automatically added to sys.path. Just make sure your setup.py includes src as a code directory. One way to do this is with:
setup(name=...
...
packages=find_packages('src'),
package_dir = {'':'src'},
...