1

Suppose there is some well-known (third-party) Python package a, which depends on another well-known package b (e.g. imageio and numpy, respectively). Both are available through pip.

Now suppose my own code explicitly uses both a and b. Package versions are fixed in my requirements.txt.

I see a few options for importing and using these packages, as described below. To me Options 2 and 3 look the cleanest, as they appear to reduce the number of dependencies that I need to manage explicitly.

Is there a preferred way of importing these packages, from the dependency management point-of-view? Or is it just a matter of style?

Option 1:

import a
import b
...
a.something()
b.something_else()
...

Option 2:

import a  # which imports b
...
a.something()
a.b.something_else()
...

Option 3:

import a
from a import b
...
a.something()
b.something_else()
...

p.s. The following questions seem related but do not provide an answer: 1, 2, 3, 4

djvg
  • 11,722
  • 5
  • 72
  • 103
  • 1
    I choose option 1 as I am not certain when library `a` will use lib `c` in place of `b` in future – anuragal Sep 20 '17 at 09:10
  • If you don't need to complicate things, don't. Just do whatever seems to be instinctive (which I'm fairly certain is Option 1 for most people). – Wiggy A. Sep 20 '17 at 09:16

2 Answers2

3

You should always manage your direct dependencies explicitly and not depend on internal implementation details of 3rd party packages. Those may change with future updates (unless a 3rd party package explicitly states that it exposes some particular package) and your code will break. If you depend on package b, put it into your requirements.txt and import b explicitly.

deceze
  • 510,633
  • 85
  • 743
  • 889
0

A maxim in the Python community is: "flat is better than nested." For this reason, I dislike Option 2. It is less readable. Also, if package A should ever change the way that it organizes its namespace, Option 2 could break.

Options 1 and 3 read identically within the main body of the code, so I have trouble choosing between them.

John Ladasky
  • 1,016
  • 8
  • 17
  • Thanks. But isn't option 3 a variation of 2, as it gets `b` from `a`? – djvg Sep 20 '17 at 09:21
  • It's true that options 2 and 3 both get `b` from `a`. But the nested function call is less readable than the flat one. Also, user "anuragal" pointed out that Option 3 suffers from the same import dependency that I identified in Option 2. Now I feel comfortable choosing Option 1 over the other two choices. – John Ladasky Sep 20 '17 at 10:04