I'm building a large application, a game-engine if you so will. I've tried both relative and absolute imports but nothing seems to be working.
As seen, I'm inside of Sacra/Screen/main.py and want to import something located in Sacra/Audio/PlayAudio.py; The part of which is a "simple" class.
To relate to the "problem", how can one do to import that class? I've looked through the bulk of python docs, real python and many more websites and all I get is the same, that it should be working as of right now.
Note: I've also tried ..Audio.PlayAudio import PlaySound, where PlaySound is the class in PlayAudio.
Another note: It's possbile to import in the Sacra, being a test.py file, with the code, import Audio. Because the init file is configuered.
Related
OK, prerequisites:
It's my first ever Python project. I used to do some scripting but never anything bigger
So I'm at the very beginning of a learning curve. It's like when you can't kill an ant in Fallout 2 Temple level. On later levels, I was really good in Fall 2:)
Problem:
I can't figure out how to import a module written by me and placed in a different folder
Context:
The project I'm intended to create is meant to do a lot of measures conversions. So I decided to store in DB all data in the same unit system & keep all conversions upon user preferences on a codebase level
In a different folder I decided to store tests. To write the very first one (testing the abovementioned module) I need to import the module, but here is the story begins. I know it's classic, but I'm completely messed with import
Toolkit:
PyCharm Pro (PyCharm 2021.3.1)
Python 3.7 interpreter
macOS 10.15, Intell
Set up:
Settings screenshot provided
Project structure. Folders are marked as Source & Test
I need to import from conversions.py to test_conversions.py
PYTHONPATH settings like this
What do I, for the sake of God, need:
with all the abovementioned, how do I import conversions.py to test_conversions.py or any other place of my project? I read a number of articles and it's getting me anywhere (contradictory, 2.x related, etc). I feel like I need a piece of more foundational info but as well I need a clear walkthrough, a code snippet to import bloody file, I really appreciate any kind of advice
imports are a bit tricky. The issue you have is where your python is looking for packages. I would discourage you to add to your PYTHONPATH a specific project but you could do that locally in your file.
A much easier way is just to launch your test file from the top directory.
In this case your import will just be import conversion.conversion
And then you can launch your test from the root folder with python -m tests.conversion.
In Pycharm you can use the interface to deal with that, see this link. But I like the python -m because it works from anywhere, not only inside Pycharm.
make a class inside a conversion.py, then you can import it from test_conversion.py.
conversion.py
class convert():
def km_to_mm(input):
output = input * 1000000
return output
then import it in test_conversion.py
input = 0.001 # specify your input value
from conversion import convert
converted = convert().a_to_b(input)
converted will have value 1000
make sure you use the same folder. otherwise should use folder name to import. like
import foldername.conversion
from foldername.conversion import convert
I really appreciate all of you who tried to help. I got the problem solved in a very ridiculous manner, below is to someone who might face the same issue in the future.
So, in case you see the next:
You use PyCharm (no idea how other IDEs behave)
You created a module & want to import it into other files of your project
You type import module_name
While you type it, the string looks active and autocomplete even proposes you your module name but as only you finished typing, the import string turns grey, PyCharm throws you a warning saying Unused import statement, yellow bulb next to the import string suggests you delete the import string
--> This does not mean you are not able to import your module, it means you've done it and now can call anything from your module in the code below.
This taught me to pay some more time to read docs before jumping to using anything new and think better about UX in anything I do.
I am working on documenting a piece of code using ReadTheDocs (RTD). Here is the GitHub repo that it builds off, and below it is the current state of the website:
Repo: https://github.com/GluonicPenguin/AutoDQM
RTD: https://autodqm.readthedocs.io/en/latest/index.html
I have run a Sphinx-build locally and checked the build on RTD, and I get no warnings or errors, but the autodqm/dqm.py module does not display the list of functions properly on RTD, i.e. the lists of functions aren't appearing. I had an issue with autodqm/compare_hists.py as well, and I found the issue was I had an import ROOT line at the top (with the other import lines), which when the import is called through a ROOT() function, for some reason this cures the issue and the autodqm/compare_hists.py module displays properly on the website.
I thought a similar fix would work with autodqm/dqm.py but in this case, I have to define near the top the functions
def lxml():
import lxml.html
return lxml.html
def FuturesSession():
from requests_futures.sessions import FuturesSession
return FuturesSession
and I have to remove the class DQMSession. At most I can think that RTD doesn't like handling import functions of the form import <package>.<subpackage>.
I also apologise in advance for all the commits and vague/poor commit messages - I was doing this exhaustively, and developing this locally rather than on GitHub, so I had to keep pushing to test this.
Is there a reason why the setup I currently have doesn't work? Are there other issues that I'm missing? I've never used Sphinx/RTD before, so I'm a novice when it comes to fixing things like this. The reason why I'm not wanting to support the quick fix above with "segregated" import functions is this code needs to be efficient given it is designed to scan through a lot of histograms to perform stats comparisons on, which on that scale efficiency is essential.
Based on Steve's response above, I fixed the issue in AutoDQM RE failing to import modules, so now all the functions display properly on the website. The fixes were:
dqm.py - requests-futures and lxml now requirements specified in setup.py, which are pip installed via
install_requires=['lxml==4.5.2','requests-futures==1.0.0']
compare_hists.py - import ROOT fixed using extension autodoc_mock_imports from autodoc, so there is a line in docs/conf.py autodoc_mock_imports = ["ROOT"]. We need the requirement like this because it is a package with C dependencies, so can't be pip installed like the others.
Thanks for your help!
I have two py files and have simplified my problem of just a few lines.
One:
from Two import PrintTwo
class PrintOne(object):
print('HelloOne')
Two:
from One import PrintOne
class PrintTwo(object):
print('HelloTwo')
This brings up this message: cannot import name 'PrintTwo' as expected.
But my problem is I need to use some functions of these classes in both files.
I cant find a solution for that, how is the correct workflow for a case like this?
Kind regards
This is called circular importing and they can work, if you set them up properly. However, I'd not recommend using circular imports and rather refactor the code.
It's hard to say what to change on the code, if I don't see it. When I experience circular imports then I try to avoid them by refactoring the code. Possible solutions are:
Move bits of the "shared" code into an own Python module (recommended)
Lazy import a module/component, means only import it when you use it (works but not really shiny)
I can't show you an example based on the code above, because you only circular import the modules but don't use them.
As mentioned before, a workaround is using imports only when you use them, for example:
class PrintOne:
def some_magic_method(self):
from Two import PrintTwo
I have a small annoyance with PyCharm; for example if I am writing assert_true without having it imported, then I can Alt-Enter on it and I get the suggestion to Import from... nose.tools.assert_true and the ide automatically adds the line:
from nose.tools import assert_true
Thats all good. But if I later write assert_false and press Alt-Enter I don't seem to have the choice to add that to the existing import automatically. Seem odd to me, do I miss something ?
So currently what I do is to add the first function like that and then I have to add additional functions manually to the existing import lines.
I know you can use * and to import the full module; but I am still interested in on how to automatically add further functions to existing import lines in some non manual way.
Update: as in the comments below this seem to be specific to nose.tools, when importing from other modules it works.
So I just met a strange so-called bug. Because this work on my other .py files, but just on this file it suddenly stopped working.
from tuttobelo.management.models import *
The above used to work, but it stopped working all of a sudden, and I had to replace it with the bottom.
from tuttobelo.management.models import Preferences, ProductVariant, UserSeller, ProductOwner, ProductModel, ProductVariant
from tuttobelo.management.models import ProductMeta, ShippingMethods
I know the following is the better way of coding, however ALL of the models mentioned in models are used, so my question is, what possible reasons can wildcard stop working?
The error I got was that the model I was trying to import does not exist, only if I remove the wildcard and import the name of the model could I get it imported properly.
Thanks!
Maybe the models module has an __all__ which does not include what you're looking for. Anyway, from ... import * is never a good idea in production code -- we always meant the import * feature for interactive exploratory use, not production use. Specifically import the module you need -- use that name to qualify names that belong there -- and you'll be vastly happier in the long run!-)
There are some cases in Python where importing with * will not yield anything. In your example, if tuttobelo.management.models is a package (i.e. a directory with an __init__.py) with the files Preferences.py, ProductVariant.py, etc in it, importing with star will not work, unless you already have imported it explicitly somewhere else.
This can be solved by putting in the __init__.py:
__all__ = ['Preferences', 'ProductVariant', 'UserSeller', <etc...> ]
This will make it possible to do import * again, but as noted, that's a horrible coding style for several reasons. One, tools like pyflakes and pylint, and code introspection in your editor, stops working. Secondly, you end up putting a lot of names in the local namespace, which in your code you don't know where they come from, and secondly you can get clashes in names like this.
A better way is to do
from tuttobelo.management import models
And then refer to the other things by models.Preferences, models.ProductVariant etc. This however will not work with the __all__ variable. Instead you need to import the modules from the __init__.py:
import Preferences, ProductVariant, UserSeller, ProductOwner, <etc...>
The drawback of this is that all modules get imported even if you don't use them, which means it will take more memory.