0

I am trying to set up a library in python. I have created a setup.py file and in a folder under that I have a library folder, and then I tried to create an sample and test folder (for sample code and tests that I would include)

Folders:

- setup.py
- cvImageUtils # this is the library
     - __init__.py # this includs ColorUtils
     - ColorUtils.py # this includes a class called ColorUtils
- examples
     - color.py # this is shown below

init.py in ColorUtils folder

from . import ColorUtils

ColorUtils.py

class ColorUtils:
    def __...

Color.py

from cvImageUtils import ColorUtils
m1 = cv2.imread(os.path.join(image_folder, "bb.jpeg"), 1)  # 1 = load color
cv2.imshow('grayscale', ColorUtils.convert_rbg_to_grayscale(m1))

At first, it said, unable to find the module, so I added to the top of the file the following based on another SO solution:

import sys
sys.path.append('../')

Now that seems broken to me already, but it did get me past the no module found, but now it says ColorUtils has no method convert_rbg_to_grayscale. So Then I had to change it to ColorUtils.ColorUtils.convert_rbg_to_grayscale

cv2.imshow('grayscale', ColorUtils.ColorUtils.convert_rbg_to_grayscale(m1))

How can I setup the folder so that it allows me to include the library without sys, and call it without declaring ColorUtils twice.

nycynik
  • 7,371
  • 8
  • 62
  • 87

2 Answers2

2

change your __init__.py:

from cvImageUtils.ColorUtils import ColorUtils

I don't think you'll need to import sys anymore, and you don't have import ColorUtils twice. but just like you have to instantiate an object, you should create a ColorUtils object.

my personal preference would be not creating a Class for Utils.

you might have done this already, but if you want to use a method straight from a class like you did in python, you might want to declare it static.

class ColorUtils:
      @staticmethod
      def util_method():
          pass

then you can just do:

ColorUtils.util_method()

Update:

you can read more about relative/absolute import from here as well.

to fix your actual problem though, you can do:

color.py

  1. remove your import sys and sys call from color.py

  2. change: import cvImageUtils.ColorUtils as ct
    to: from cvImageUtils.ColorUtils import *

  3. remove all your ct reference instead just use the actual functions.

cvImageUtils/__init__.py

change: from . import ColorUtils to __all__=['ColorUtils']

I was able to run color.py to get all the images printed out on screen. a image.png was also generated locally as well.

Community
  • 1
  • 1
stucash
  • 1,078
  • 1
  • 12
  • 23
  • I see, most of the Utils are @staticmethod anyway. So I think that is a better approach, and by making the functions global, it seems to read better in the imports. – nycynik Dec 21 '17 at 14:52
  • @nycynik if you think any of us solves problem, give it a tick :P thanks! – stucash Dec 21 '17 at 14:55
  • If I remove the sys call, I still get `ModuleNotFoundError: No module named 'cvImageUtils'` – nycynik Dec 21 '17 at 14:56
  • @nycynik could you try above? if not, do it with two dots before. – stucash Dec 21 '17 at 15:12
  • import ..cvImageUtils <= `SyntaxError: invalid syntax` – nycynik Dec 21 '17 at 15:18
  • @nycynik you meant `from ..cvImageUtils import ColorUtils`? note it's `from` – stucash Dec 21 '17 at 15:19
  • The . would imply it is in this folder, so where should I run python from? When I go into the examples folder, and run `python3 color.py` with the sys import '..' it works. – nycynik Dec 21 '17 at 15:20
  • Okay - with that I get `from ..cvImageUtils import ColorUtils ValueError: attempted relative import beyond top-level package` – nycynik Dec 21 '17 at 15:20
  • I'm going to live with the import ../ from sys at the top fo the example file. – nycynik Dec 21 '17 at 15:22
  • I am thinking it's something to do with your folder structure here. I replicated your structure locally (but only as far as you shared above), it worked for me without sys. but when I did `from .Utils.ColorUtils import ColorUtils` I got exactly that `NoModule` error. – stucash Dec 21 '17 at 15:24
  • Thank you for helping me with this, I added a git repo here - https://github.com/nycynik/cvImageUtils – nycynik Dec 21 '17 at 15:35
  • @nycynik my pleasure! ok that's great, let me copy it locally first. – stucash Dec 21 '17 at 15:36
  • 1
    @nycynik hey I think I fixed it for you, but I am behind proxy so I can't raise the PR on github. I'll do it here. (yes I can still download it locally :)) – stucash Dec 21 '17 at 15:56
1

Every directory that you want to expose in module search(we usually hide test.py) in python need a init.py file. That should be rule of thumb, by using sys module you can add the module to your "module search path".

After having init.py in your directories, you need to import packages/modules/funcitons you want to use:-

import cvImageUtils.ColorUtils.convert_rbg_to_grayscale

You can execute following code in python to see, what have included in your sys path(used by python to search for modules/packages)

import sys
sys.path

Look into below links for more detailed explations
https://www.programiz.com/python-programming/package
https://www.programiz.com/python-programming/modules#search

Muku
  • 538
  • 4
  • 18
  • it's not that absolute. your tests folder normally wouldn't have a `__init__.py` because you normally are not going to expose any of your test to other module/library. – stucash Dec 21 '17 at 14:37
  • Okay! I added the import as `from cvImageUtils.ColorUtils import ColorUtils ` I did not realize that the file and class are not the same. I assumed import `ColorUtils` would mean, from the file, import the class with the same name. – nycynik Dec 21 '17 at 14:50