为什么要这样干呢?因为 Python 虽然号称跨平台,但是一些和操作系统相关的函数 API,windows 下也还是只能干瞪眼用不了,比如 import fcntl 这在 windows 下是没法用的,这就给开发测试带来了不便,在两个异构系统上,没法无缝切换 work。因此,能想到的就是利用 windows 上的 Cygwin 模拟 linux,然后 Pycharm 去调用 Cygwin 下的 Python 即可。
CYGWIN_HOME=D:\Cygwin_64bit
Path=C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;f:\OpenV**\bin;%JAVA_HOME%\bin;%SCALA_HOME%\bin;%CYGWIN_HOME%\lib;%CYGWIN_HOME%\bin;%CYGWIN_HOME%\usr\sbin;%CYGWIN_HOME%\lib\python2.7;%CYGWIN_HOME%\usr\include\python2.7;%CYGWIN_HOME%\usr\include;D:\phantomjs-2.0.0-windows\bin;%MINGW_HOME%\mingw32\bin;D:\Kerberos\bin;C:\Program Files\MIT\Kerberos\bin;F:\SCRT
PYTHONPATH=%CYGWIN_HOME%\lib;%CYGWIN_HOME%\bin;%CYGWIN_HOME%\usr\sbin;%CYGWIN_HOME%\lib\python2.7;%CYGWIN_HOME%\usr\include\python2.7;%PYTHONPATH%
# 以下3个和本文主题无关,备份之用
LIBRARY_PATH=%CYGWIN_HOME%\lib
MINGW_HOME=D:\C-Free5\mingw
C_INCLUDE_PATH=%CYGWIN_HOME%\lib\gcc\x86_64-pc-cygwin\5.3.0;%CYGWIN_HOME%\lib\gcc\x86_64-pc-cygwin\5.3.0\include\c++;%CYGWIN_HOME%\lib\gcc\mingw32\3.4.5\include
代码请使用《300行python代码的轻量级HTTPServer实现文件上传下载》来测试,这份的代码的特点是在 windows 下会报错,linux 正常,因为使用了 linux 下特有的模块:fcntl
然而我们却在 IDE 里看到语法报错了:
这是为毛?
sys 和 time 模块居然会找不到???
然后小心翼翼的先 alt + shift + x 执行试试,居然 working 正常!
由于想到 sys 和 time 都属于内置模块,可能和 python.exe 这个可执行文件有关,于是先 copy 了一个 windows 版的 python.exe 过去试试,重新加载就没有语法报错的问题了。
但是上面的疑问还是没解决:为什么 time 和 sys 模块找不到居然还能执行成功呢?
第一反应就是找找看 time 在哪里。搜索了 python 安装目录,发现根本就找不到 time.py 或者 time.pyc,然后继续查看系统环境:
import sys
# for i in sys.modules.keys():
# print i
# print sys.path
import time
# print time.__file__
import imp
# print imp.find_module('time')
# print help(imp)
# import datetime
# print datetime.__file__
# D:\Cygwin_64bit\bin\python2.7.exe F:/sourceDemo/flask/study/flumeFileMonitor/t1.py
# /usr/lib/python2.7/lib-dynload/datetime.dll
import fcntl
print fcntl.__file__
当 解释器是 windows 版本时,time.__file__ 会抛异常,根本就找不到 time 模块路径,是不是很奇怪,那平时咱们 import time 是怎么执行成功的呢?
搜了下 SF 发现了答案:
原来 windows 下的这些内置模块都是 C 写的,是没有 time.__file__ 属性,也就是看不到源码的,而在linux下则会指向一个 .so 文件。
当解释器是 Cygwin 版本时,time.__file__ 结果是:/usr/lib/python2.7/lib-dynload/time.dll
至此,我们能看到这两个版本的 python.exe 各有优劣:
但是我们没有办法可以让 Pycharm 既能支持 linux 特性也能拥有内置模块语法检查与代码提示功能。说到底这是一个熊掌与鱼不可兼得的问题。
最后要说下,我还尝试了另一个方案:自己在 Cygwin 下编译 Linux 版 Python 源码,但是和 Cygwin 自带 Python 一样,存在同样的问题。而且编译过程当中还遇到报错了:
File "./setup.py", line 2041, in configure_ctypes
exec f in fficonfig
File "build/temp.cygwin-2.4.1-x86_64-2.7/libffi/fficonfig.py", line 33, in <mo dule>
ffi_sources += ffi_platforms['X86_WIN64']
KeyError: 'X86_WIN64'
Makefile:513: recipe for target 'sharedmods' failed
make: *** [sharedmods] Error 1
解决方案是将第 33 行的 X86_WIN64 改成 X86_64 即可通过编译。
ffi_sources = """
src/prep_cif.c
src/closures.c
""".split()
ffi_platforms = {
'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'],
'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'],
'X86': ['src/x86/ffi.c', 'src/x86/sysv.S', 'src/x86/win32.S'],
'X86_FREEBSD': ['src/x86/ffi.c', 'src/x86/freebsd.S'],
'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'],
'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'],
'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'],
'IA64': ['src/ia64/ffi.c', 'src/ia64/unix.S'],
'M32R': ['src/m32r/sysv.S', 'src/m32r/ffi.c'],
'M68K': ['src/m68k/ffi.c', 'src/m68k/sysv.S'],
'POWERPC': ['src/powerpc/ffi.c', 'src/powerpc/ffi_sysv.c', 'src/powerpc/ffi_linux64.c', 'src/powerpc/sysv.S', 'src/powerpc/ppc_closure.S', 'src/powerpc/linux64.S', 'src/powerpc/linux64_closure.S'],
'POWERPC_AIX': ['src/powerpc/ffi_darwin.c', 'src/powerpc/aix.S', 'src/powerpc/aix_closure.S'],
'POWERPC_FREEBSD': ['src/powerpc/ffi.c', 'src/powerpc/sysv.S', 'src/powerpc/ppc_closure.S'],
'AARCH64': ['src/aarch64/sysv.S', 'src/aarch64/ffi.c'],
'ARM': ['src/arm/sysv.S', 'src/arm/ffi.c'],
'LIBFFI_CRIS': ['src/cris/sysv.S', 'src/cris/ffi.c'],
'FRV': ['src/frv/eabi.S', 'src/frv/ffi.c'],
'S390': ['src/s390/sysv.S', 'src/s390/ffi.c'],
'X86_64': ['src/x86/ffi64.c', 'src/x86/unix64.S', 'src/x86/ffi.c', 'src/x86/sysv.S'],
'SH': ['src/sh/sysv.S', 'src/sh/ffi.c'],
'SH64': ['src/sh64/sysv.S', 'src/sh64/ffi.c'],
'PA': ['src/pa/linux.S', 'src/pa/ffi.c'],
'PA_LINUX': ['src/pa/linux.S', 'src/pa/ffi.c'],
'PA_HPUX': ['src/pa/hpux32.S', 'src/pa/ffi.c'],
}
ffi_sources += ffi_platforms['X86_64']
ffi_cflags = ' -Wall -fexceptions'
说到底文章开头的想法最终也没能行得通,也罢,windows Pycharm 下还是老老实实的用 windows 版 Python 吧,Cygwin 下用 vim 凑合得了~
[1] How do I find the location of Python module sources?
http://stackoverflow.com/questions/269795/how-do-i-find-the-location-of-python-module-sources
[2] Error with libffi while installing Python 2.7.5 on Cygwin 64
https://github.com/yyuu/pyenv/issues/61
[3] Re: Unable to compile python 3.3 [Was: Re: Python 3.3 coming soon?]