import python module with one file inside - python

I packaged one file:
proxy_master
├── __init__.py
└── proxy_master.py
After installing it, i need to type:
from proxy_master import proxy_master
I want to know is it even possible just type?
import proxy_master
Thanks! Advices to change something may be good too, i did all like mentioned here https://packaging.python.org/en/latest/tutorials/packaging-projects/

Related

Importing files from different folder in the same parent directory

I've got a folder that looks something like this. I'm trying to import a class from card.py from test_cards.py
└── 32-PROJECT-Texas-Hold-Em-Poker/
├── poker/
│ ├── card.py
│ └── __init__.py
└── tests/
└── test_cards.py
└── __init__.py
In test.py I've tried:
from poker import card
from .poker import card
from ..poker import card
from 32-PROJECT-Texas-Hold-Em-Poker.poker import card
import sys
sys.path.insert(1, '/path/to/Test_folder_1/Test_folder_2')
from Test_folder_2 import add_numbers
but it keeps coming up with either No module named poker or ImportError: attempted relative import with no known parent package. I've tried different variations along with varying where the init.py file is, and honestly I've tried a lot more than what I posted above. I've read up on relative and absolute imports. Short of adding this directory right into my path, I'm completely lost at what seems to be a simple task. I've spend a couple of days on this now and I just can't seem to get it to work. Also, what should I be studying to understand this stuff better rather than finding stuff online? I've just recently learnt about system paths and venvs.
I'm actually following along with The complete Python bootcamp for 2022 on Udemy
from test_cards.py, he is able to get a Card class from card.py just from typing
from poker.card import Card
Thank you
There are a few ways to do this. Here's one that's quite simple, suitable for test code but not recommended in a production app:
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'poker'))
import card
sys.path = sys.path[:-1]
That should work no matter where you run your Python script from.
Here's some more information: https://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python

How do I manipulate the default import path of a Python Project?

This is a little complex, I'll try to simplify as much as possible.
I want to create .pyi files for Brython, in a separate, installable, package.
Consider that I have a main project with a Brython file, myfile.py
The file should start with an import exactly like this -- exactly.
from browser import document
In my installable project, I have a structure such as this;
../brython-signatures/src/
└── brython
├── browser
│   ├── document.pyi
│   └── __init__.py
└── __init__.py
I install this second tool (during testing) with the following;
pip install -e ~/Projects/brython-signatures
This forces me to use the following import statement;
from brython.browser import document
For reasons beyond the scope of this question, I do not want to change the structure (e.g. make 'browser' the root package).
Question Is there a clever way to make my main application think it should import browser instead of brython.browser.
I tried adding package-dir entry to the installable project.
[package-dir]
browser="src/brython/browser"

Is there a way to import a python package from another python package, as if it was part of the same code?

Let's say that we have python packages package_a and package_b. As a user, I want to be able to say:
from package_a.package_b import some_functionality
My question is: is there a way to support this without literally copy-pasting the code of package_b to package_a?
EDIT 1:
To clarify, I have shadow naming (my python package is named the same way as my folder), and I am wondering if there was a way to make the python package available somewhere else.
And yes, I'm looking into ways how to rename the package/folder in a way it still makes sense in the domain.
This is an abuse of Python's module system, and I would urge you to reconsider this design, but if you really must, you can do it by messing with sys.modules:
In package_a/__init__.py:
import sys
import package_b
sys.modules[__name__ + '.package_b'] = package_b
You can see something like this in the standard lib, os.path is either thentpath or posixpath module depending on platform, neither of which is actually part of os (it couldn't be, os is a module, not a package).
https://github.com/python/cpython/blob/master/Lib/os.py
sys.modules['os.path'] = path
With setuptools you can do something like this:
Project
├── setup.py
└── src
├── package_a
│   └── __init__.py
└── package_b
└── __init__.py
setup.py
#!/usr/bin/env python3
import setuptools
setuptools.setup(
name='Project',
version='0.0.7',
packages=[
'package_a',
'package_b',
'package_a.package_b',
],
package_dir={
'package_a': 'src/package_a',
'package_b': 'src/package_b',
'package_a.package_b': 'src/package_b',
},
)
This will effectively install two copies of package_b, one as a top level package and another one as a sub-package of package_a. Which could be a problem since if for example you have a global variables in package_b then it won't have the same value as the same global variable in package_a.package_b. But it might as well be a positive side effect, depending on the use cases.

Python relative imports with sys.path

I have this weird Python import and I can't get it to work with any of the suggestions in other discussions.
I'm currently adding a small script to someone else's module, so I cannot change the file structure or any of the existing code, which makes things difficult.
Here is an example of the python script which contains a bunch of classes:
/path/to/root/directory/aaa/bbb/ccc/utils.py
The current developer imports this as follows:
from aaa.bbb.ccc import utils
utils.SomeClass.someMethod()
All directories in the tree have a __init__.py file
Now I want to call the module externally as follows:
import sys
sys.path.append('/path/to/root/directory')
from aaa.bbb.ccc import utils
utils.SomeClass.someMethod()
This does NOT work, and gives the the following error:
from aaa.bbb.ccc import utils
ImportError: No module named ccc
However, changing the import a little bit does work:
import sys
sys.path.append('/path/to/root/directory')
from aaa.bbb.ccc.utils import *
SomeClass.someMethod()
I do not understand why the 2nd one works and not the 1st. Again, I cannot change the existing code, so the following 2 statements must work with my sys.path.append and imports:
from aaa.bbb.ccc import utils
utils.SomeClass.someMethod()
I cannot remove the utils from utils.SomeClass
Does anyone know how I can achieve this?
This really isn't an answer, but there is no way I could fit this into a comment, let alone with any sane formatting. My apology, but it hopefully can still help us get somewhere.
I suspect there is still a bit of information missing somewhere in the question. I've setup the following tree under /tmp/so/xxx:
.
└── aaa
├── __init__.py
└── bbb
├── __init__.py
└── ccc
├── __init__.py
└── utils.py
__init__.py files are blank and utils.py says:
class SomeClass:
#staticmethod
def someMethod():
print("FOO")
Which if I read the description correctly should be enough to replicate the behavior. Now I try both snippets of yours:
import sys
sys.path.append("/tmp/so/xxx")
from aaa.bbb.ccc import utils
utils.SomeClass.someMethod()
And run:
$ python test1.py
FOO
And second one:
import sys
sys.path.append("/tmp/so/xxx")
from aaa.bbb.ccc.utils import *
SomeClass.someMethod()
Runs as well:
$ python test2.py
FOO
I've tried Python 3.6.5 and 2.7.15. Same result.
Based on your output, I presume you're running Python 2. The only way I could reproduce this problem (get the same error) was by removing __init__.py from ccc/, but the other syntax would not work either then.
Could you perhaps post your tree and content of __init__.py files? With the available data, I was unfortunately able to reproduce the problem.

Python module import works for one file, fails for another

I'm facing a very strange problem. I've got three files, the first contains the base class, from which the classes in the other two files inherit from.
The strange thing is, everything worked fine yesterday, but one of the files doesn't work anymore today. I haven't touched the imports in the meantime.
.
└── orangecontrib
├──__init__.py
└── prototypes
├──__init__.py
└── widgets
├──__init__.py
├── owpythagorastree.py
├── owclassificationpythagorastree.py
└── owregressionpythagorastree.py
So the classification and regression classes need to inherit from the base class, and the imports are done in the exact same way:
owclassificationpythagorastree.py
...
from orangecontrib.prototypes.widgets.owpythagorastree import OWPythagorasTree
...
owregressionpythagorastree.py
...
from orangecontrib.prototypes.widgets.owpythagorastree import OWPythagorasTree
...
Yet when I try to run the two scripts from the command line (with python owregressionpythagorastree.py) the regression widget works fine, but the classification widget produces the following error:
Traceback (most recent call last): File
"owclassificationpythagorastree.py", line 6, in
from orangecontrib.prototypes.widgets.owpythagorastree import OWPythagorasTree ImportError: No module named
'orangecontrib.prototypes'
This has happened several times in other projects as well, but it eventually sorts itself out. But it bothers me that I don't know what is causing this.
I did try running this both from my regular machine and a python virtualenv, where I have the module installed (I did this with pip install -e . in the base directory).
I see no apparent reason for this behaviour and it is bothering me a lot, so any help or insight as to why this is happening and how to fix it would be appreciated.
EDIT
As requested, I ran import sys; print(sys.path) at the top of both scripts, and after running it through diff, they are both completely identical. Nevertheless, I am posting the results here.
['/home/pavlin/dev/orange3-prototypes/orangecontrib/prototypes/widgets',
'/home/pavlin/dev/orange3',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages/setuptools_git-1.1-py3.5.egg',
'/home/pavlin/dev/orange-bio',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages/pyqtgraph-0.9.10-py3.5.egg',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages/requests-2.9.1-py3.5.egg',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages/slumber-0.7.1-py3.5.egg',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages/Genesis_PyAPI-1.2.0-py3.5.egg',
'/usr/lib/python3.5/site-packages/qt_graph_helpers-0.1.3-py3.5-linux-x86_64.egg',
'/home/pavlin/dev/orange3-prototypes',
'/usr/lib/python3.5/site-packages',
'/home/pavlin/dev/orange3env/lib/python35.zip',
'/home/pavlin/dev/orange3env/lib/python3.5',
'/home/pavlin/dev/orange3env/lib/python3.5/plat-linux',
'/home/pavlin/dev/orange3env/lib/python3.5/lib-dynload',
'/usr/lib64/python3.5', '/usr/lib/python3.5',
'/usr/lib/python3.5/plat-linux',
'/home/pavlin/dev/orange3env/lib/python3.5/site-packages',
'/usr/lib/python3.5/site-packages/setuptools-18.7.1-py3.5.egg',
'/home/pavlin/.local/lib/python3.5/site-packages']
It looks like your problem is a not-complete understanding of how python finds modules.
For an absolute import (i.e. one where you specify the name of the first module such as import mymodule, and don't use a period to do a relative import from the package to which the code belongs, such as from . import mymodule), the order of lookups is:
The current directory.
Any directories in PYTHONPATH in your environment.
Any installed system paths, which may be set in various ways.
To see your complete set of paths to import from, use:
import sys
print(sys.path)
Also, remember that a directory is only importable if it has an __init__.py file – you didn't say whether that was the case or not with your code.
Therefore, provided you have the following layout:
.
└── orangecontrib
├── __init__.py
└── prototypes
├── __init__.py
└── widgets
├── __init__.py
├── owpythagorastree.py
├── owclassificationpythagorastree.py
└── owregressionpythagorastree.py
I would expect that if you run python orangecontrib/prototypes/widgets/owclassificationpythagorastree.py from the base directory ., both should work just fine, without needing to modify your PYTHONPATH, since python always looks in the current directory for absolutely imported modules first.
If you are running from the widgets directory, I would expect it not to work, unless you had first added the base directory to your PYTHONPATH.
As a general hint though, except for very small things, you should avoid mixing module code with script code, for exactly these reasons! Make separate python scripts that are designed to be run from a command line, and separate python module code that is designed to be imported. Avoid making modules that can also be run from the command line as scripts.
Just a thought. Have you checked the permissions? Maybe somehow the permissions got messed up and they are giving you the problems.

Categories

Resources