43

I have some code in a project which I'd like to reuse in another project. What do I need to do (in both folders) so that I can do this?

The directory structure is something like:

  • Foo
    • Project1
      • file1.py
      • file2.py
  • Bar
    • Project2
      • fileX.py
      • fileY.py

I want to use functions from file1.py and file2.py in fileX.py and fileY.py.

ATOzTOA
  • 34,814
  • 22
  • 96
  • 117
Big Dogg
  • 2,564
  • 5
  • 21
  • 22

5 Answers5

54

Ideally both projects will be an installable python package, replete with __init__.py and setup.py. They could then be installed with python setup.py install or similar.

If that is not possible, don't use execfile()! Manipulate the PYTHONPATH to add Foo so that import Project1.file1 works.

For example, from Project2/fileX.py:

from os import path
import sys
sys.path.append(path.abspath('../Foo'))

from Project1.file1 import something

However, the real answer is to make each a discrete installable package.

Rob Cowie
  • 22,259
  • 6
  • 62
  • 56
  • 4
    Project1 and Project2 are both sitting on my server with both version controlled. If Project1 is updated, then I will have to update the installed package each time on project2. But, if I manipulate my sys.path, just doing a git pull on the Project1 will update my module. Am I doing anything smelly? Or it is okay to do it! Thanks! – Abhishek Dec 05 '17 at 05:57
  • @Rob Cowie, could you please tell me sir, how can we check, if the path is added from the other function/project – Prathamesh Doke Jul 17 '19 at 11:51
  • 1
    @Abhishek +1, typical on SO, no answer :-\ – t3chb0t Aug 28 '22 at 08:15
8

There's a lot going on here. you should read about python packages and module management http://docs.python.org/2/tutorial/modules.html#packages but the basic idea is that fileX needs to know where file1 and file2 are in order to use them.

To turn a folder into a package, it just needs to contain an __init__.py file. What I would suggest you do is (in a terminal)

$ touch Foo/__init__.py
$ touch Foo/Project1/__init__.py

(assuming you're using unix/linux).

Then somehow, fileX needs to know where the Foo package is. You can call sys.path.append(PATH) where PATH is the location of Foo.

finally inside fileX.py you'd have

import sys
sys.path.append(PATH) #replace PATH with the path to Foo

from Foo.Project1 import file1

#use its functions
file1.function_name(argument)

if you really want to just say function_name without the preceeding file1. you can import all of its functions by saying from Foo.Project1.file1 import * however please note that from module import * is highly frowned upon as it mixes names and make code less readable and understandable

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
5

You may want to make a module out of it and then import whatever you need from it.

msc
  • 3,780
  • 1
  • 22
  • 27
3

You take the code you want to use in both projects, and you put it into a module, which you extract into a third separate project. That project you make into a package, which you can work on separately. You then release version of it, and reuse them in your other projects.

It is important that you have versions that you "release" so that you can keep track of which version of the module each project uses. Otherwise you will end up in a situation where an old project stops working because you have made incompatible changes to the common module.

If it's generically usable not only for you but for others, consider uploading it to PyPI.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • @gented The question posed is "How to reuse the code", which I asked. The question is not "How do you release a package". That's a different question. – Lennart Regebro Sep 24 '19 at 04:54
-1

I think you can add Foo to the current Python path using os.path.join() or os.path.append() and do from import Project1.file1 import function_name.

Bibhas Debnath
  • 14,559
  • 17
  • 68
  • 96
  • 1
    Changes in Project1 will in a case like this tend to spuriously break Project2. Not a good idea. It meeds to be made into a module, and have versioned releases. – Lennart Regebro Jan 24 '13 at 19:36
  • 1
    This is like the literal solution to the problem. There might be other (better) ways of doing it, including the one you suggested. – Bibhas Debnath Jan 24 '13 at 19:38