Calling script in standard project directory structure (Python path for bin subdirectory)
<p>I am experimenting with putting my Python code into the standard directory structure used for deployment with <code>setup.py</code> and maybe PyPI. for a Python library called mylib it would be something like this:</p>

<pre><code>mylibsrc/
  README.rst
  setup.py
  bin/
    some_script.py
  mylib/
    __init.py__
    foo.py
</code></pre>

<p>There's often also a <code>test/</code> subdirectory but I haven't tried writing unit tests yet. The recommendation to have scripts in a <code>bin/</code> subdirectory can be found in the <a href="http://python-packaging.readthedocs.io/en/latest/command-line-scripts.html" rel="nofollow">official Python packaging documentation</a>. </p>

<p>Of course, the scripts start with code that looks like this:</p>

<pre><code>#!/usr/bin/env python
from mylib.foo import something
something("bar")
</code></pre>

<p>This works well when it eventually comes to deploying the script (e.g. to devpi) and then installing it with pip. But if I run the script directly from the source directory, as I would while developing new changes to the library/script, I get this error:</p>

<pre><code>ImportError: No module named 'mylib'
</code></pre>

<p>This is true even if the current working directory is the root <code>mylibsrc/</code> and I ran the script by typing <code>./bin/some_script.py</code>. This is because Python starts searching for packages in the directory of the script being run (i.e. from <code>bin/</code>), not the current working directory.</p>

<p>What is a good, permament way to make it easy to run scripts while developing packages? </p>

<p>Here is a <a href="http://Related%20question%20(especially%20comments%20to%20first%20answer):%20http://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application" rel="nofollow">relevant other question</a> (especially comments to the first answer).</p>

<p>Here are some alternatives I've found so far, but none of them are ideal:</p>

<ul>
<li>Install the package using setup.py into a virtual environment. This seems like overkill if I'm just testing a change that I'm not sure is even syntactically correct yet. Some of the project I'm working on aren't even meant to be installed as packages but I want to use the same directory structure for everything, and this would mean writing a setup.py just so I could test them!</li>
<li>Use the <code>setup.py develop</code> command designed for this purpose. This partially installs the package to a virtual environment, but instead of copying the files it makes a hard link to the development directory. <a href="http://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode" rel="nofollow">Here are the relevant setuptools docs.</a> (Suggested by logc in their answer below) This has the disadvantage that you still need to create a <code>setup.py</code> for packages you never intend to fully install, and doesn't work very will with PyCharm (which has a menu entry to run the <code>develop</code> command but no easy way to run the scripts that it copies to the virtual environment).</li>
<li>Manually add <code>mylibsrc</code> to my <code>PYTHONPATH</code> environment variable. This would mean that every time I check out a project I have to remember to manually change my environment before I can run any code in it.</li>
<li>Add <code>.</code> to the start of my <code>PYTHONPATH</code> environment variable. As I understand it this could have some security problems. This would actually be my favoured trick if I was the only person to use my code, but I'm not, and I don't want to ask others to do this.</li>
<li>While looking at answers on the internet, for files in a <code>test/</code> directory I've seen recommendations that they all (indirectly) include a line of code <code>sys.path.insert(0, os.path.abspath('..'))</code> (e.g. in <a href="http://docs.python-guide.org/en/latest/writing/structure/" rel="nofollow">structuring your project</a>). Yuck! This seems like a bearable hack for files that are only for testing, but not those that will be installed with the package.</li>
<li>As a last resort: Just dump all of the scripts in the root <code>mylibsrc/</code> directory instead of a <code>bin/</code> subdirectory. Unfortunately, this seems like the only feasible option at the moment.</li>
</ul>

<p>The simplest way is to use <code>setuptools</code> in your <code>setup.py</code> script, and use the <code>entry_points</code> keyword, see the documentation of <a href="http://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-script-creation" rel="nofollow">Automatic Script Creation</a>.</p>

<p>In more detail: you create a <code>setup.py</code> that looks like this</p>

<pre><code>from setuptools import setup

setup(
    # other arguments here...
    entry_points={
        'console_scripts': [
            'foo = my_package.some_module:main_func',
            'bar = other_module:some_func',
        ],
        'gui_scripts': [
            'baz = my_package_gui:start_func',
        ]
    }
)
</code></pre>

<p>then create other Python packages and modules underneath the directory where this <code>setup.py</code> exists, e.g. following the above example:</p>

<pre><code>.
âââ my_package
âÂ Â  âââ __init__.py
âÂ Â  âââ some_module.py
âââ my_package_gui
âÂ Â  âââ __init__.py
âââ other_module.py
âââ setup.py
</code></pre>

<p>and then run</p>

<pre><code>$ python setup.py install
</code></pre>

<p>or</p>

<pre><code>$ python setup.py develop
</code></pre>

<p>Either way, new Python scripts (executable scripts without the <code>.py</code> suffix) are created for you that point to the entry points you have described in <code>setup.py</code>. Usually, they are at the Python interpreter's notion of "directory where executable binaries should be", which is usually on your PATH already. If you are using a virtual env, then <code>virtualenv</code> tricks the Python interpreter into thinking this directory is <code>bin/</code> under wherever you have defined that the virtualenv should be. Following the example above, in a virtualenv, running the previous commands should result in:</p>

<pre><code>bin
âââ bar
âââ baz
âââ foo
</code></pre>

python setup.py