I'm currently using Python 3.7 and Pycharm for my work. Recently I got a code that is done at Python2.7
You shouldn't use Python 3.7 to run code that was written for Python 2.x, unless you can port that code to Python 3, or you know that it works fine. There are some caveats, and it depends on what the functionality of that code is. In some cases it might be very time consuming to convert it. 2to3 might help here.
So, depending on your use case, you may want to keep a legacy version of Python 2.7 around on your system to run that particular code, but note that Python 2.x will not get any (security) updates anymore, so you're better off using Python 3 from now on.
Try running the code in Python 3.7 and see if it works.
and it includes a library named 'ctypes.'
This is included by default in Python, so you don't need to install anything. Assuming you have the correct Python 2.7 interpreter and all other required packages, the code should just run fine as-is.
If the person who wrote the code was doing a good job, he or she should have left a README and/or a requirements.txt file or something similar that would specify which other packages or libraries are needed to run it.
I'm currently using Python 3.7 and Pycharm for my work. Recently I got a code that is done at Python2.7
You shouldn't use Python 3.7 to run code that was written for Python 2.x, unless you can port that code to Python 3, or you know that it works fine. There are some caveats, and it depends on what the functionality of that code is. In some cases it might be very time consuming to convert it. 2to3 might help here.
So, depending on your use case, you may want to keep a legacy version of Python 2.7 around on your system to run that particular code, but note that Python 2.x will not get any (security) updates anymore, so you're better off using Python 3 from now on.
Try running the code in Python 3.7 and see if it works.
and it includes a library named 'ctypes.'
This is included by default in Python, so you don't need to install anything. Assuming you have the correct Python 2.7 interpreter and all other required packages, the code should just run fine as-is.
If the person who wrote the code was doing a good job, he or she should have left a README and/or a requirements.txt file or something similar that would specify which other packages or libraries are needed to run it.
This S.O question has an answer which says
You don't need to install ctypes at all; it is part of the Python standard library, as of Python 2.5 onwards. See the module documentation.
which was provided by @MartijnPieters who has over 700k rep and so, presumably, knows what he is talking about.
In the conda documentation for using shared libraries, different approaches are described depending on the operating system. On Linux, shared libraries in conda packages typically have a modified rpath (using patchelf). For example:
>>> import importlib.util
>>> importlib.util.find_spec("_ctypes").origin
'<$CONDA_PREFIX>/lib/python3.10/lib-dynload/_ctypes.cpython-310-x86_64-linux-gnu.so'
CONDA_PREFIX/lib/python3.10/lib-dynload/
$ ldd _ctypes.cpython-310-x86_64-linux-gnu.so
linux-vdso.so.1 => (0x00007ffe565c0000)
libffi.so.8 => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007fadad8de000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fadad6c2000)
libc.so.6 => /lib64/libc.so.6 (0x00007fadad2f4000)
/lib64/ld-linux-x86-64.so.2 (0x00007fadadae2000)
Since libffi is not found, in python an import ctypes will give the error: ImportError: libffi.so.8: cannot open shared object file: No such file or directory. Now, libffi is installed as a conda package in this case, so
$ patchelf --set-rpath '$ORIGIN/../..' _ctypes.cpython-310-x86_64-linux-gnu.so
will fix that problem. Now if I create a shared library test.c:
#include <stdio.h>
void special()
{
printf("special\n");
}
and compile it i.e. cc -shared -fPIC -o special.so test.c, Then special.so will exist in this directory but ctypes won't be able to find it. Now, if I do cp special.so $CONDA_PREFIX/lib, then in Python loading it works fine:
>>> import ctypes
>>> ctypes.cdll.LoadLibrary("special.so")
<CDLL 'special.so', handle f86430 at 0x7ff44691e5f0>
>>> libsp = ctypes.CDLL("special.so")
>>> x = libsp.special()
special
On windows, to answer your specific question, the documentation states:
This path [
(install prefix)\\Library\\bin] is added to os.environ["PATH"] for all Python processes, so that DLLs can be located, regardless of the value of the system's PATH environment variable. This is the difference between the "raw" and the conda installation.
See also: How does conda work internally?
You're actually being caught out by the addition of os.add_dll_directory in Python 3.8, and the associated change to only load DLLs from safe directories, and the fact that Anaconda undid that change for their own builds.
Essentially, using the PATH environment variable to choose code to execute is these days considered insecure. Windows allows it by default in regular installs, but it can be disabled by a parent process or an administrator. To avoid the potential confusion due to inconsistent behaviour, Python 3.8 started changing the default itself. That way, users would know by checking for os.add_dll_directory whether they could (probably) modify PATH or if they should use the proper function.
Anaconda found that too many libraries broke with this change, and rather than fixing the libraries, decided to change it back for their build of Python. As of 3.10, they are no longer doing this and the behaviour should be consistent.
As a workaround, if you load your DLL using the full path instead of just the name, it will work consistently everywhere.
As for your example with ctypes: DLLs can only be loaded once-per-process. After it has been loaded once, attempting to load it again will succeed regardless of the settings used. So using the (unpatched) ctypes from Anaconda succeeds, and then the (patched) ctypes doesn't even consider search paths because the DLL is already in memory.
If you tried to load a different DLL the second time, it should fail again.
» pip install ctypeslib2
Installing libffi-dev and re-installing python3.7 fixed the problem for me.
to cleanly build py 3.7 libffi-dev is required or else later stuff will fail
If using RHEL/Fedora:
sudo yum install libffi-devel
or
sudo dnf install libffi-devel
If using Debian/Ubuntu:
sudo apt-get install libffi-dev
If you use pyenv and get error "No module named '_ctypes'" (like i am) on Debian/Raspbian/Ubuntu you need to run this commands:
sudo apt-get install libffi-dev
pyenv uninstall 3.7.6
pyenv install 3.7.6
Put your version of python instead of 3.7.6