What files are required for Py_Initialize to run?
<p>I am working on a simple piece of code that runs a Python function from a C/C++ application. In order to do this I set the PYTHONPATH and run initialize as follows:</p>

<pre class="lang-c++ prettyprint-override"><code>Py_SetPythonHome("../Python27");
Py_InitializeEx(0);
</code></pre>

<p>Then I import my module and run my function. It works great.</p>

<p>I am now attempting to build an installer for my colleagues to run my code. I want to minimize the number of files I need to include in this installer, for obvious reasons.</p>

<p>Googling around the subject tells me that I should be able to include the files "Python27.lib" and "Python27.dll", then zip the "DLLs" and "Lib" folders and include them. However, when I attempt this, Py_Initialize fails. </p>

<p>A quick examination of what is causing this failure shows that Py_Initialize appears to depend upon a number of .pyc files in the Lib folder including (but not limited to <em>warnings.pyc</em>, <em>_abcoll.pyc</em>, <em>_future_.pyc</em> and the contents of the "encodings" folder.</p>

<p>I cannot understand why this would be. Any advice?</p>

<p>At the beginning I wanted to say that there's no module required (at least no <em>non-builtin</em> one) for <code>Py_InitializeEx</code>, so the only requirement was <em>python27.dll</em> (btw: <em>python27.lib</em> is <strong>not</strong> required, unless your colleagues want to link something against it - but that wouldn't be very easy w/o <em>Python</em>'s <em>Include</em> dir). I had this code (<strong>BTW</strong>: I am using <em>Python 2.7.10</em> that I built using <em>Visual Studio 10.0</em>):</p>

<pre><code>#include &lt;stdio.h&gt;
#include &lt;conio.h&gt;
#include &lt;Python.h&gt;

int main() {
    int i = 0;
    char *pyCode = 
        "s = \"abc\"\n"
        "print s, 1234";
    Py_InitializeEx(0);
    i = PyRun_SimpleString(pyCode);
    Py_Finalize();
    printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
    _getch();
    return 0;
}
</code></pre>

<p>It built fine, it ran OK from <em>Visual Studio</em>, and from the command line (after copying the <em>.dll</em> in its folder). But then I copied the <em>.exe</em> and <em>.dll</em> to another computer and when running, <em>bang!!!</em></p>

<blockquote>
  <p>ImportError: No module named site</p>
</blockquote>

<p>Considering that:</p>

<ul>
<li>I have no <em>PYTHON*</em> env vars set in neither of the consoles on the 2 machines where I ran the <em>.exe</em> (with different results)</li>
<li>On both machines the <em>Python</em> installation is on the same path (I modified it on the machine that doesn't work)</li>
</ul>

<p>I don't know why it doesn't behave the same (one thing that I haven't check is that there might be some registry key on the machine that works?).</p>

<p><em>Note</em>: <code>site</code> is a (<em>.py(c)</em>) module located under <em>%PYTHON_INSTALL_DIR%\Lib</em>.</p>

<p>Then, I browsed <em>Python</em>'s source code and I came across this (file: <em>pythonrun.c</em>, line: <em>269</em>, function <code>Py_InitializeEx</code> or <em>pythonrun.c:269:<code>Py_InitializeEx</code></em> - this is how I'm going to refer a point in the source code):</p>

<pre><code>    if (!Py_NoSiteFlag)
        initsite(); /* Module site */
</code></pre>

<p>while in <em>pythonrun.c:727:<code>initsite</code></em>:</p>

<pre><code>    m = PyImport_ImportModule("site");
</code></pre>

<p>which is pretty obvious (<code>Py_NoSiteFlag</code> is 0).</p>

<p>Then I noticed that <code>Py_NoSiteFlag</code> is declared as <a href="https://msdn.microsoft.com/en-us/library/aa299338(v=vs.60).aspx" rel="nofollow"><code>extern</code></a> <a href="https://msdn.microsoft.com/en-us/library/3y1sfaz2(v=vs.100).aspx" rel="nofollow"><code>__declspec(dllexport)</code></a>, so I modified my code to:</p>

<pre><code>#include &lt;stdio.h&gt;
#include &lt;conio.h&gt;
#include &lt;Python.h&gt;

extern __declspec(dllimport) int Py_NoSiteFlag;

int main() {
    int i = 0;
    char *pyCode = 
        "s = \"abc\"\n"
        "print s, 1234";
    Py_NoSiteFlag = 1;
    Py_InitializeEx(0);
    i = PyRun_SimpleString(pyCode);
    Py_Finalize();
    printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
    _getch();
    return 0;
}
</code></pre>

<p>and it works! Yay!</p>

<p>So, at this point only the <em>.dll</em> is required in order to run a piece of code. But I imagine that your code is "a little bit" more complex than that (it has <a href="https://docs.python.org/2.0/ref/import.html" rel="nofollow"><code>import</code></a>s). To solve the <em>import</em> problem, you can use this nice module called <a href="https://docs.python.org/2/library/modulefinder.html?highlight=modulefinder#module-modulefinder" rel="nofollow"><code>modulefinder</code></a> (part of <em>Python 2.7</em>'s standard modules). To make use of it:</p>

<ul>
<li>save the code that you execute from <em>C</em> in a <em>.py</em> file</li>
<li>run <code>modulefinder</code> against it</li>
</ul>

<p>Here's an example for my code (<code>pyCode</code> contents in my <em>C</em> program, saved in a file called <em>a.py</em>):</p>

<pre><code>s = "abc"
print s, 1234
</code></pre>

<p>Running <code>%PYTHON_INSTALL_DIR%\python %PYTHON_INSTALL_DIR%\Lib\modulefinder.py a.py</code> yields:</p>

<blockquote>
  <p><code>Name                      File</code><BR>
  <code>----                      ----</code><BR>
  <code>m __main__                a.py</code></p>
</blockquote>

<p><strong>But</strong>, if I add an <code>import os</code> (which is a pretty common module) statement in the file, the above command yields:</p>

<blockquote>
  <p><code>Name                        File</code><BR>
  <code>----                        ----</code><BR>
  <code>m StringIO                  %PYTHON_INSTALL_DIR%\lib\StringIO.py</code><BR>
  <code>m UserDict                  %PYTHON_INSTALL_DIR%\lib\UserDict.py</code><BR>
  <code>m __builtin__</code><BR>
  <code>m __future__                %PYTHON_INSTALL_DIR%\lib\__future__.py</code><BR>
  <code>m __main__                  a.py</code><BR>
  <code>m _abcoll                   %PYTHON_INSTALL_DIR%\lib\_abcoll.py</code><BR>
  <code>m _codecs</code><BR>
  <code>m _collections</code><BR>
  <code>m _functools</code><BR>
  <code>m _hashlib                  %PYTHON_INSTALL_DIR%\DLLs\_hashlib.pyd</code><BR>
  <code>m _heapq</code><BR>
  <code>m _io</code><BR>
  <code>m _locale</code><BR>
  <code>m _random</code><BR>
  <code>m _sre</code><BR>
  <code>m _struct</code><BR>
  <code>m _subprocess</code><BR>
  <code>m _threading_local          %PYTHON_INSTALL_DIR%\lib\_threading_local.py</code><BR>
  <code>m _warnings</code><BR>
  <code>m _weakref</code><BR>
  <code>m _weakrefset               %PYTHON_INSTALL_DIR%\lib\_weakrefset.py</code><BR>
  <code>m abc                       %PYTHON_INSTALL_DIR%\lib\abc.py</code><BR>
  <code>m array</code><BR>
  <code>m atexit                    %PYTHON_INSTALL_DIR%\lib\atexit.py</code><BR>
  <code>m bdb                       %PYTHON_INSTALL_DIR%\lib\bdb.py</code><BR>
  <code>m binascii</code><BR>
  <code>m cPickle</code><BR>
  <code>m cStringIO</code><BR>
  <code>m cmd                       %PYTHON_INSTALL_DIR%\lib\cmd.py</code><BR>
  <code>m codecs                    %PYTHON_INSTALL_DIR%\lib\codecs.py</code><BR>
  <code>m collections               %PYTHON_INSTALL_DIR%\lib\collections.py</code><BR>
  <code>m copy                      %PYTHON_INSTALL_DIR%\lib\copy.py</code><BR>
  <code>m copy_reg                  %PYTHON_INSTALL_DIR%\lib\copy_reg.py</code><BR>
  <code>m difflib                   %PYTHON_INSTALL_DIR%\lib\difflib.py</code><BR>
  <code>m dis                       %PYTHON_INSTALL_DIR%\lib\dis.py</code><BR>
  <code>m doctest                   %PYTHON_INSTALL_DIR%\lib\doctest.py</code><BR>
  <code>m dummy_thread              %PYTHON_INSTALL_DIR%\lib\dummy_thread.py</code><BR>
  <code>P encodings                 %PYTHON_INSTALL_DIR%\lib\encodings\__init__.py</code><BR>
  <code>m encodings.aliases         %PYTHON_INSTALL_DIR%\lib\encodings\aliases.py</code><BR>
  <code>m errno</code><BR>
  <code>m exceptions</code><BR>
  <code>m fnmatch                   %PYTHON_INSTALL_DIR%\lib\fnmatch.py</code><BR>
  <code>m functools                 %PYTHON_INSTALL_DIR%\lib\functools.py</code><BR>
  <code>m gc</code><BR>
  <code>m genericpath               %PYTHON_INSTALL_DIR%\lib\genericpath.py</code><BR>
  <code>m getopt                    %PYTHON_INSTALL_DIR%\lib\getopt.py</code><BR>
  <code>m gettext                   %PYTHON_INSTALL_DIR%\lib\gettext.py</code><BR>
  <code>m hashlib                   %PYTHON_INSTALL_DIR%\lib\hashlib.py</code><BR>
  <code>m heapq                     %PYTHON_INSTALL_DIR%\lib\heapq.py</code><BR>
  <code>m imp</code><BR>
  <code>m inspect                   %PYTHON_INSTALL_DIR%\lib\inspect.py</code><BR>
  <code>m io                        %PYTHON_INSTALL_DIR%\lib\io.py</code><BR>
  <code>m itertools</code><BR>
  <code>m keyword                   %PYTHON_INSTALL_DIR%\lib\keyword.py</code><BR>
  <code>m linecache                 %PYTHON_INSTALL_DIR%\lib\linecache.py</code><BR>
  <code>m locale                    %PYTHON_INSTALL_DIR%\lib\locale.py</code><BR>
  <code>P logging                   %PYTHON_INSTALL_DIR%\lib\logging\__init__.py</code><BR>
  <code>m marshal</code><BR>
  <code>m math</code><BR>
  <code>m msvcrt</code><BR>
  <code>m nt</code><BR>
  <code>m ntpath                    %PYTHON_INSTALL_DIR%\lib\ntpath.py</code><BR>
  <code>m opcode                    %PYTHON_INSTALL_DIR%\lib\opcode.py</code><BR>
  <code>m operator</code><BR>
  <code>m optparse                  %PYTHON_INSTALL_DIR%\lib\optparse.py</code><BR>
  <code>m os                        %PYTHON_INSTALL_DIR%\lib\os.py</code><BR>
  <code>m os2emxpath                %PYTHON_INSTALL_DIR%\lib\os2emxpath.py</code><BR>
  <code>m pdb                       %PYTHON_INSTALL_DIR%\lib\pdb.py</code><BR>
  <code>m pickle                    %PYTHON_INSTALL_DIR%\lib\pickle.py</code><BR>
  <code>m posixpath                 %PYTHON_INSTALL_DIR%\lib\posixpath.py</code><BR>
  <code>m pprint                    %PYTHON_INSTALL_DIR%\lib\pprint.py</code><BR>
  <code>m random                    %PYTHON_INSTALL_DIR%\lib\random.py</code><BR>
  <code>m re                        %PYTHON_INSTALL_DIR%\lib\re.py</code><BR>
  <code>m repr                      %PYTHON_INSTALL_DIR%\lib\repr.py</code><BR>
  <code>m select                    %PYTHON_INSTALL_DIR%\DLLs\select.pyd</code><BR>
  <code>m shlex                     %PYTHON_INSTALL_DIR%\lib\shlex.py</code><BR>
  <code>m signal</code><BR>
  <code>m sre_compile               %PYTHON_INSTALL_DIR%\lib\sre_compile.py</code><BR>
  <code>m sre_constants             %PYTHON_INSTALL_DIR%\lib\sre_constants.py</code><BR>
  <code>m sre_parse                 %PYTHON_INSTALL_DIR%\lib\sre_parse.py</code><BR>
  <code>m stat                      %PYTHON_INSTALL_DIR%\lib\stat.py</code><BR>
  <code>m string                    %PYTHON_INSTALL_DIR%\lib\string.py</code><BR>
  <code>m strop</code><BR>
  <code>m struct                    %PYTHON_INSTALL_DIR%\lib\struct.py</code><BR>
  <code>m subprocess                %PYTHON_INSTALL_DIR%\lib\subprocess.py</code><BR>
  <code>m sys</code><BR>
  <code>m tempfile                  %PYTHON_INSTALL_DIR%\lib\tempfile.py</code><BR>
  <code>m textwrap                  %PYTHON_INSTALL_DIR%\lib\textwrap.py</code><BR>
  <code>m thread</code><BR>
  <code>m threading                 %PYTHON_INSTALL_DIR%\lib\threading.py</code><BR>
  <code>m time</code><BR>
  <code>m token                     %PYTHON_INSTALL_DIR%\lib\token.py</code><BR>
  <code>m tokenize                  %PYTHON_INSTALL_DIR%\lib\tokenize.py</code><BR>
  <code>m traceback                 %PYTHON_INSTALL_DIR%\lib\traceback.py</code><BR>
  <code>m types                     %PYTHON_INSTALL_DIR%\lib\types.py</code><BR>
  <code>P unittest                  %PYTHON_INSTALL_DIR%\lib\unittest\__init__.py</code><BR>
  <code>m unittest.case             %PYTHON_INSTALL_DIR%\lib\unittest\case.py</code><BR>
  <code>m unittest.loader           %PYTHON_INSTALL_DIR%\lib\unittest\loader.py</code><BR>
  <code>m unittest.main             %PYTHON_INSTALL_DIR%\lib\unittest\main.py</code><BR>
  <code>m unittest.result           %PYTHON_INSTALL_DIR%\lib\unittest\result.py</code><BR>
  <code>m unittest.runner           %PYTHON_INSTALL_DIR%\lib\unittest\runner.py</code><BR>
  <code>m unittest.signals          %PYTHON_INSTALL_DIR%\lib\unittest\signals.py</code><BR>
  <code>m unittest.suite            %PYTHON_INSTALL_DIR%\lib\unittest\suite.py</code><BR>
  <code>m unittest.util             %PYTHON_INSTALL_DIR%\lib\unittest\util.py</code><BR>
  <code>m warnings                  %PYTHON_INSTALL_DIR%\lib\warnings.py</code><BR>
  <code>m weakref                   %PYTHON_INSTALL_DIR%\lib\weakref.py</code><BR></p>
  
  <p><code>Missing modules:</code><BR>
  <code>? _emx_link imported from os</code><BR>
  <code>? ce imported from os</code><BR>
  <code>? fcntl imported from subprocess, tempfile</code><BR>
  <code>? org.python.core imported from copy, pickle</code><BR>
  <code>? os.path imported from os, shlex</code><BR>
  <code>? os2 imported from os</code><BR>
  <code>? posix imported from os</code><BR>
  <code>? pwd imported from posixpath</code><BR>
  <code>? readline imported from cmd, pdb</code><BR>
  <code>? riscos imported from os</code><BR>
  <code>? riscosenviron imported from os</code><BR>
  <code>? riscospath imported from os</code><BR></p>
</blockquote>

<p>As you can see, there is an awfully lot of modules (I modified the output a little bit, instead of the actual path I placed the <em>%PYTHON_INSTALL_DIR%</em> env var). In order for the <em>Python</em> code to work, you'll have to include all of those modules/packages in the installer.</p>

<p>Notes about <code>modulefinder</code>'s output (that I've noticed while playing with it):</p>

<ul>
<li>It searches for modules recursively, so here is the whole module dependency tree</li>
<li>It searches for <em>import</em> statements located in functions (so, not only the ones at module level)</li>
<li>It <strong>doesn't</strong> search for dynamic imports (e.g. <a href="https://docs.python.org/2/library/functions.html#__import__" rel="nofollow">__import__</a>)</li>
</ul>

<p>So, looking at the modules that are required by <code>os</code>, I'm not sure that taking out the <code>site</code> import from <em>C</em> makes much of a difference.</p>

<p><strong>IMPORTANT NOTE</strong>: To make sure your <em>.exe</em> works on any computer, you might consider including <em>Visual Studio C runtime library</em> (<a href="https://msdn.microsoft.com/en-us/library/59ey50w6(v=vs.100).aspx" rel="nofollow">msvcr##(#).dll</a>) (where <em>#</em> s are placeholders for digits - representing <em>Visual Studio</em> version) in your installer.</p>

python c++ ctypes embedding