I'm new to Python and am working through its idiosyncrasies, and am having problems with something that should be simple. I have main directory with main.py and some other files, and I have a subfolder holding classes for some specific processing. So let's say my file structure looks like this:
root/main.py
root/more/foo.py
root/more/bar.py
File foo looks like this:
from bar import bar
class Foo():
def __init__():
myBar = bar()
if __name__ == '__main__':
G = Foo()
print(G.myBar)
Main.py looks like:
import more.foo as f
.
.
.
When this line is called, the interpreter has no problem finding foo, but the import line raises an error in foo.py:
ModuleNotFoundError: No module named 'bar'
When I run foo natively, it has no problem finding bar and functions effectively. Can you help me what's going on here, and what I can do to circumvent this issue?
I'm running Python 3.7 in OSX using PyCharm.
I am assuming that when you say you run foo natively, you are in the folder more.
To solve your issue, you simply need to import all classes everywhere in relation to its position from the root directory, because the entry point is in main.py.
This should work if you import bar from more.bar:
from more.bar import bar
Related
I wanted to port some code from python 2 to python 3 and it failed on an import error. So I tried to get rid of the porting itself and focus on the import by creating 2 basic python files to test with. However I can't even get those to work.
So I have 2 files
test.py:
print('Test works')
and test2.py:
from . import test
The result however is this error in Pycharm:
ImportError: cannot import name 'test' from '__main__'
(C:/Users/Username/test2.py)
In Ubuntu Shell:
Traceback (most recent call last): File "test2.py", line 1, in
from . import test1 SystemError: Parent module '' not loaded, cannot perform relative import
How can I solve it?
This "folder structure matters" is a large problem in python3. Your folder structure should NOT matter when coding, but should be referenced properly.
I've just resorted to using if/else depending on if ran locally or as part of a module:
if __name__ == "__main__": # Local Run
import test
else: # Module Run, When going production - delete if/else
from . import test
In Python3
test2.py:
import test
test.py:
if __name__ == "__main__":
print('Test works')
If you want to print "Test works" in other file
test2.py:
import test
test.main()
test.py:
def main():
print('Test works')
if __name__ == "__main__":
main()
The folder structure matters. You didn't name your module; I will call it foo. Put things in the right place:
$ mkdir foo
$ touch foo/__init__.py
$ mv /some/place/{test1,test2}.py foo/
Notice that python -c 'import test' works already, even before you wrote your test.py file. To avoid confusion I recommend naming your file test1.py.
The way you call your code matters. Verify that . dot is in sys.path:
$ export PYTHONPATH=.
$ python -m foo.test1
Alternatively this should work, if you prefer:
$ python foo/test1.py
EDIT:
I answered question #1, and OP now asks question #2, about this diagnostic:
ImportError: cannot import name 'test' from 'main' (C:/Users/Username/test2.py)
Please organize your files in the proper structure. You need to put test2.py within a foo/ directory (or whatever you care to call it). You need to create an empty foo/__init__.py file, as that is important for the import machinery.
Also, the PYTHONPATH env var in the calling environment matters. In addition to the command line environment, you have now introduced a PyCharm environment. Take care to configure PyCharm correctly for your project. Click on Preferences -> Project Structure and ensure that foo shows up as a Source Folder. You can debug this in either environment by executing these lines:
import sys
import pprint
pprint.pprint(sys.path)
Since import test would succeed even without your project being in place, I recommend you rename to test1.py and use import test1 so you can be sure you're pulling in your code.
I had the same problem, and ended up removing the "from . " that was added from the 2to3 conversion script.
if I have written a unittest, that passes, if I run my tests.py in IDE Pycharm. If I use the console (in unix) however and start the unittest with:
python3 tests/tests.py
I get the following error:
ModuleNotFoundError: No module named 'helpermodule'
My folder structure looks like this:
folder structure
The files look like the following:
Mytest.py:
def add(x,y):
return x+y
tests.py:
from helpermodule import Mytest
import unittest
What am I missing here? I have read several posts concerning the problem, but I could not find a solution that worked.
If anyone has the same problem, the simple solution is to call the test.py with right parameters:
python3 -m unittest tests/tests.py
see also:
https://docs.python.org/3/library/unittest.html#command-line-interface
I have a folder
/
alphabet/
__init__.py
a.py
b.py
...
main.py
The modules in alphabet/ have to be unknown to me, and I want to access them when importing from main.py, so this is what alphabet/__init__.py looks like
from os import listdir, path
onlyfiles = [f for f in listdir('alphabet') if path.isfile(path.join("alphabet", f))]
__all__ = [f[:-3] for f in onlyfiles if f != '__init__.py' and f[-2:] == "py"]
And that how main.py calls them
import alphabet
modules = [l for l in alphabet.__all__]
print(modules)
["a", "b", ...]
Now I want to run a function named sound() from a.py
for m in modules:
alphabet.m.sound()
But it gives this error AttributeError: module 'alphabet' has no attribute 'm'
There are so many things wrong with this it's difficult to begin. You can reference the following to begin debugging your application:
In your for loop, you cannot use the variable m in a dotted notation, as the interpreter will try to access the literal m module and not the variable name. A valid way to try that would be to call alphabet.__all__[m].sound(). But it won't actually work since you never imported that part of the code. The correct way is to use the importlib module and load submodules on the fly, something like
import importlib
module = importlib.import_module('alphabet.a')
How you build the function attribute for import_module is up to you.
Furthermore putting the submodule names in __all__ only exposes them to the importer (or hides them) and doesn't actually import them at runtime. You have to use import * from alphabet to import all the submodules in __all__.
I would strongly recommend you research package development for python and return to this.
I found an easier solution in which I use eval()
for m in modules:
eval('alphabet.{}.sound()'.format(m))
I was wondering if it was possible for modules in a project to be smart about their imports...
Say I have the following data structure :
/parent-directory
/package
__init__.py
main.py
/modules
__init__.py
one.py
/submodules-one
__init__.py
oneone.py
onetwo.py
two.py
Files higher in the hierarchy are supposed to import Classes from those lower in the hierarchy.
For instance main.py has
import modules.one
import modules.two
Now I'd like to be able to directly run not only main.py, but also one.py (and all the others)
Except that it doesn't work like I hoped :
If I run from main.py, I need to have in one.py
import modules.submodules-one.oneone
import modules.submodules-one.onetwo
But if I run from one.py, I'll get an error, and I need to have instead
import submodules-one.oneone
import submodules-one.onetwo
I've found a hacky way to get around it using in one.py :
if __name__ == '__main__':
import submodules-one.oneone
import submodules-one.onetwo
else:
import modules.submodules-one.oneone
import modules.submodules-one.onetwo
But isn't there a better solution?
P.S.: I also have an additional complication, I'm using pint,
which to work properly only needs to have a single instance of the unit registry, so I have in the top ____init____.py :
from pint import UnitRegistry
ur = UnitRegistry()
And obviously
from .. import ur
will fail if running from one of the files of the subfolders.
Thank you in advance for your answer.
I have a very simple file setup:
test.py
package/
__init__.py
file_1.py
With the contents of each file being:
# in test.py
import package
# in file_1.py
foo = 5
With the __init__ file being blank. I've been told on multiple occasions that leaving the __init__ file blank is perfectly fine. Then why then, in test.py can I not access foo by saying package.foo? This seems incredibly trivial to me, yet I cannot figure out why it's not working. If I put a print function in file_.py that doesn't seem to get activated either upon running test.py, so what is my problem?
It doesn't work like this. You cannot access package.foo since there is no foo in package.__init__. Since code in __init__ doesn't import file_1 or file_1.foo.
You can do import package.file_1 and then access package.file_1.foo or from package.file_1 import foo and then access foo.
Also there can be no __init__.py at all.