I'm not that fluent in Python so I'm not sure if what I'm doing is common practice or the proper way to do it.
I'm creating a module archive contaning files with one class each, e.g. SmsArchiveReader.py with class SmsArchiveReader inside. To make the imports less tedious, I decided to import the classes directly into the __init__.py.
However, both Spyder and Pylint have issues with my __init__.py, with Spyder telling me that I shouldn't have unused imports, and Pylint telling me that I shouldn't use absolute imports. Both suggestions seem pointless to me, since this is __init__.py we're talking about, but I'm open to suggestions.
Image below:
As for the look I wanted to achieve, I wanted the code using this module to look like that:
import archive
myReader = archive.SmsArchiveReader()
myReader2 = archive.FooArchiveReader()
instead of:
import archive
myReader = archive.SmsArchiveReader.SmsArchiveReader()
myReader2 = archive.FooArchiveReader.FooArchiveReader()
So what's the correct practice of creating modules?
As jonrsharpe said, it's a problem with Spyder IDE. This issue has been submitted to their bug tracker, the interested can follow its status on Github.
Related
Suppose I do some data analysis within a particular folder. Some Juypter Notebooks some .py files. Is it possible (and does it makes sense) to define the imports globally in one file ? e.g. import numpy as np and now I can use np.whatever in every file ? Maybe this is a stupid question but a colleague of mine who is using R, asked me this question and I never thought of that idea.
EDIT: For the downvoters: I really tried to find that out my searching on the net but could not find any information. I thought that this would not be a good idea but who knows.
While it may not be a 'good' idea in general, it could be a good idea for you. If you create a script in a folder with your imports and import that as a module elsewhere, you can import the other modules with it. The syntax would be from my_convenience_imports import *
My question here is more about the appropriate way to resolve import errors in a way that is considered "Pythonically correct," if there is such a term. I thought I had solution to my problem (posted below and updated), but even that turns out not work.
Context
I have looked at various responses to this (like How to resolve import errors in python?) and I think I've done those things, but I still have the question that I'm posting here.
Example
I have the following structure:
pacumen
rules
__init__.py
pacman_rules.py
pacman.py
game.py
In pacman_rules.py I have a class:
class PacmanRules:
....
In my pacman.py file, I have the following import statement:
from rules.pacman_rules import PacmanRules
Mind you, this was auto-generated by PyCharm. So PyCharm shows me that it resolves just fine.
However, when I run pacman.py from the command line, I get the following error:
ImportError: cannot import name PacmanRules
I have no idea why that's happening in this case, given the lines of code.
In pacman.py I also have this statement:
from game import GameStateData
That one is working just fine. Notice that the class GameStateData comes from my game.py file. So I'm guessing my issue is that I'm trying to import from a file in a different directory rather than from a file in the same directory.
Possible Solution (Update: Does Not Work)
So then I tried this import instead:
from rules import pacman_rules
That seems to work, but it requires me to change lines like this:
PacmanRules.getLegalActions(self)
to lines like this:
pacman_rules.PacmanRules.getLegalActions(self)
That just feels messy to me and seems to defeat the purpose of importing a class name so I can use it without having to preface it.
But, as it turns out, this doesn't work either. This just gets a different error:
ImportError: cannot import name pacman_rules
So that's my question here. Most questions seem to revolve around how to fix the issue; as it turns out I don't even have a "fix."
What I'm curious about is why the initial approach doesn't work (especially since PyCharm generates it) and if my proposed solution is the appropriate way to handle this.
I've looked on many sites and many related questions, but following the solutions to those questions still didn't seem to help. I figured maybe I am missing something, so here goes.
My project is to create a DM's tool for managing table top role playing games. I need to be able to split my project into many different files in order to keep everything organized. (so far) I have only three files I'm trying to work with. I have my main file which I called dmtool.py3, I have a file for class definitions called classdef.py3, and I have a file for creating race objects called races.py3.
1] The first of my questions is regarding importing singular files. I've tried organizing the files in several different ways, so for this lets assume all of my three files are in the same directory.
If I want to import my class definitions from classdef.py3 into my main file dmtool.py3, how would I do that? import classdef and import classdef.py3 do not seem to work properly saying their is no module with that name.
2] So I then made a module, and it seemed to work. I did this by creating a sub-directory called defs and putting the classdef.py3 and races.py3 files into it. I created the __init__.py3 file, and put import defs in dmtool.py3. As a test I put x = 1 at the very top of races.py3 and put print("X =", defs.x) in dmtool.py3. I get an error saying that module doesn't have an attribute x.
So I guess my second question is if it is possible to just use variables from other files. Would I use something like defs.x or defs.races.x or races.x or maybe simply x? I can't seem to find the one that works. I need to figure this out because I will be using specific instances of a class that will be defined in the races.py3 file.
3] My third question is a simple one that kind of spawned from the previous two. Now that races.py3 and classdef.py3 are in the same module, how do I make one access the other. races.py3 has to use the classes defined in classdef.py3.
I would really appreciate any help. Like I said I tried looking up other questions related to importing, but their simple solutions seemed to come up with the same errors. I didn't post my specific files because other than what I mentioned, there is just very simple print lines or class definitions. Nothing that should affect the importing.
Thanks,
Chris
Firstly, do not use .py3 as a file extension. Python doesn't recognize it.
Python 3's import system is actually quite simple. import foo looks through sys.path for a package (directory) or module (.py file) named foo.
sys.path contains various standard directories where you would normally install libraries, as well as the Python standard library. The first entry of sys.path is usually the directory in which the __main__ script lives. If you invoke Python as python -m foo.bar, the first entry will instead be the directory which contains the foo package.
Relative imports use a different syntax:
from . import foo
This means "import the foo module or package from the package which contains the current module." It is discussed in detail in PEP 328, and can be useful if you don't want to specify the entire structure of your packages for every import.
Start python and type these commands:
>>> import sys
>>> sys.path
The path is the list of directories where python looks for libraries. If your modules are not on the list, none are found.
Is there any way to create a virtual import path in Python?
My directory structure is like this:
/
native
scripts
some.py
another.py
[Other unrelated dirs]
The root is the directory from where the program is executed. Atm I add native/scripts/ to the search path so I can do import some, another instead of from native.scripts import some, another, but I'd like to be able to do it like this:
from native import some
import native.another
Is there any way to achieve this?
Related questions:
Making a virtual package available via sys.modules
Why not move some.py and another.py out into the native directory so that everything Just Works and so that people returning to the source code later won't be confused about why things are and aren't importable? :)
Update:
Thanks for your comments; they have usefully clarified the problem! In your case, I generally put functions and classes that I might want to import inside, say, native.some where I can easily get to them. But then I get the script code, and only the script code — only the thin shim that interprets arguments and starts everything running by passing those to a main() or go() function as parameters — and put that inside of a scripts directory. That keeps external-interface code cleanly separate from code that you might want to import, and means you don't have to try to fool Python into having modules several places at once.
In /native/__init__.py, include:
from scripts import some, another
We've got a series of code projects in different parts of our source tree that all have a base package company_name, and some of them import functionality from eachother. This works just fine when running the code, setuptools and declare_namespace handle peicing together the modules. However, pylint doesn't seem to be feeling the mojo, so a large number of files have large high-prio errors Unable to import X from company_name. PYTHONPATH doesn't help, maybe some magic in pylints --init-hook=? Any hints and ideas super welcome!
I have similar problem with import directory-based settings from many projects at once.
My dirty solution is to make symlinks, each with different name (eg. projectA/settings -> projA_settings, projectB/settings -> projB_settings) and then use that import:
import projA_settings
or
import projB_settings