Nuitka打包

nuitka使用参考(windows)

官方文档

安装

安装C编译器

mingw64下载页面

页面拉到最下面,目前最新版本为8.1.0,

x86_64-posix-sjlj

x86_64-posix-seh

x86_64-win32-sjlj

x86_64-win32-seh

i686-posix-sjlj

i686-posix-dwarf

i686-win32-sjlj

i686-win32-dwarf

附上版本区别详解供参考

64位系统建议选择x86_64-posix-sjlj

32位系统建议选择i686-posix-sjlj

官方文档中说要设置一下环境变量,实际使用过程中发现不设置也可以正常使用

安装python

下载python,同样按自己系统下载对应的版本

安装nuitka

python -m pip install nuitka

如果是anaconda

conda install -c conda-forge nuitka

简单测试

新建hello.py

def talk(message):

    return "Talk " + message



先直接用python运行,看看有没有语法错误

python hello.py

然后进行构建

nuitka  hello.py

命令结束后会生成一个exe,运行exe和执行上面第一条命令效果一样。

复杂一点的测试,引用一个模块

为了测试模块引用,我们将上面的文件拆分成两部分

新建mdl.py

def talk(message):

    return "Talk " + message

hello.py

from mdl import talk



def main():

    print( talk("Hello World"))


if __name__ == "__main__":

    main()

同样按上面的顺序进行构建

先直接用python运行,看看有没有语法错误

python hello.py

然后进行构建

nuitka  hello.py

使用这条命令生成的exe可以正常运行。

但如果将生成的exe拷贝到其他路径执行,将会执行失败,提示找不到mdl模块,这是因为使用上述命令生成的exe里面是并不包含上面的mdl模块,于是在执行该exe的时候,它会尝试去调用mdl.py,如果找不到mdl.py,当然就会提示找不到模块,这和py文件的执行原理是一样的。

exe同级目录下面会有一个python3x.dll文件,执行exe文件时,如果需要调用外部模块,需要这个文件的支持。

关于python3x.dll

python3x.dll是与版本相对应的,如果是python3.8.3,那么就是python38.dll。实际上,这个文件和python安装目录下面的python3x.dll是同一个文件(的拷贝)。python3x.dll相当于一个运行时(runtime),类似于javac,或者微软的framwork,python代码通过nuitka生成了二进制代码(exe或者pyd),但仍然通过python3x.dll保留了python的特性,比如调用一个python模块

现在将整个目录拷贝到其他路径,可以发现exe能够正常执行,因为此时exe文件能够通过python3x.dll找到mdl.py。

如果不想借助python3x.dll去调用模块,就要将这个模块打包进exe

nuitka --follow-import-to=mdl hello.py

再次将生成的exe单独拷贝到其他地方执行,可以看到能够正常运行,此时不再需要拷贝python3x.dll和其他任何的文件。

打包模块与follow import

上面的命令中使用了参数--follow-import-to,这个参数位于Control the recursion into imported modules这一部分,这部分参数一共有五个

    --follow-stdlib, --recurse-stdlib

                        Also descend into imported modules from standard

                        library. This will increase the compilation time by a

                        lot. Defaults to off.

    --nofollow-imports, --recurse-none

                        When --recurse-none is used, do not descend into any

                        imported modules at all, overrides all other recursion

                        options. Defaults to off.

    --follow-imports, --recurse-all

                        When --recurse-all is used, attempt to descend into

                        all imported modules. Defaults to off.

    --follow-import-to=MODULE/PACKAGE, --recurse-to=MODULE/PACKAGE

                        Recurse to that module, or if a package, to the whole

                        package. Can be given multiple times. Default empty.

    --nofollow-import-to=MODULE/PACKAGE, --recurse-not-to=MODULE/PACKAGE

                        Do not recurse to that module name, or if a package

                        name, to the whole package in any case, overrides all

                        other options. Can be given multiple times. Default

                        empty.

这一部分参数可以说是nuitka的核心。nuitka能够根据py文件中的import语句找到所有引用的库,然后将这些库文件打包进二进制文件中。找到import,然后follow,所以是follow import。所有被导入的库可以看作一个列表,而这部分参数的作用就是让用户在这个列表中进行选择,只有被选中的部分会被打包进exe

全选

--follow-imports, --recurse-all

不选

--nofollow-imports, --recurse-none

仅选择标准库

--follow-stdlib, --recurse-stdlib

仅选择指定模块/包

--follow-import-to=MODULE/PACKAGE, --recurse-to=MODULE/PACKAGE

不选择指定模块/包,这个选项会覆盖其他递归选项,也就是说最后用

--nofollow-import-to=MODULE/PACKAGE, --recurse-not-to=MODULE/PACKAGE

如果某些库没有被打包进exe,程序仍会试图通过python3x.dll去搜索路径中查找这些库,然后进行调用,调用方式跟py文件一模一样。

nuitka打包相对来说是比较耗费时间的,特别是针对像pandas这样的大家伙,所以在最终发布之前,可以暂时不对这些库进行打包(--nofollow-imports),而是将这些库手动拷贝到搜索路径中,比如exe同级目录。只要能够找到这些库,程序就能正常运行,否则会提示no module named xxx

注意:这部分参数仅仅能够处理py或者pyc文件,如果遇到pyd或者dll则会跳过

模块搜索路径

python程序如果引用了其他模块(代码中使用了import语句),就会到搜索路径中去查找这些模块,如果找不到就会提示

no module named xxx

搜索路径有很多个,而python使用环境变量sys.path管理这些路径,可以在入口代码最开头使用

import sys print(sys.path)

查看运行环境中的sys.path,看看缺失的库是否存在于搜索路径当中。

发布一个程序

如果python程序中仅仅使用了一些自定义的模块,那么参数--follow-imports就足以达到发布的效果,一个exe外加一个python3x.dll就可以在任何电脑上运行,无论是否安装python(当然架构要对应),然而实际情况往往比较复杂,稍微强大一点的程序都会调用一些第三方库,比如pyqt,numpy,这些模块中调用了大量的pyd或者dll文件。这个时候就需要使用参数--standalone

参数--standalone默认包含参数--follow-imports,即会尝试对所有的引用到的库都进行打包,将这些库中的py或者pyc打包进exe,然后再将所依赖的二进制文件(dll或者pyd)拷贝到exe所在文件夹。只要命令能够执行完成不出错,生成的exe就可以完全脱离python环境独立运行。

depends.exe

在第一次使用--standalone时,会提示安装Dependency Walker,nuitka需要使用这个工具来解析所有的依赖,从而决定拷贝哪些文件(dll,pyd)到exe目录。命令进行的过程中会自动检测该工具是否存在,没有的话会自动提示进行下载,网络没问题的时候直接回车或者输入yes就行了,但是如果网络状况不佳,就需要提前手动下载,否则命令会因此中断。

具体步骤:手动下载和系统相匹配的版本(32位或64位),解压得到以下两个文件

depends.exe depends.dll

然后放置到对应的目录 x86的路径

C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\x86\

X64的路径

C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\x86_64\

ps:我尝试过将工具放在path中,没有用,只能放在上面的路径里面

可以通过参数--windows-dependency-tool=DEPENDENCY_TOOL将其修改为其他依赖解析工具,比如pefile,但是不建议修改。参数--windows-dependency-tool=DEPENDENCY_TOOL仅限windows系统使用

参数--mingw64

实际上 --mingw64与--msvc=MSVC是一对孪生参数,这两个参数二选一,用于指定编译器,如果当前环境既安装了mingw64,又安装了msvc,可以使用该参数选择兼容性最好的编译器,建议使用mingw64。如果不存在上面两种编译器都存在的情况,就不需要显式设置这个参数,默认会调用系统中能用的编译器。

参数plugin control

这部分参数用于设置对某些第三方库或者python功能进行支持,在使用--standalone时才会用到

如果程序中使用了pyqt或者pyside,那么

--plugin-enable=qt-plugins

如果程序中使用了numpy, scipy, pandas, matplotlib,那么

--plugin-enable=numpy

如果使用了这些库或功能,但是忘了进行插件参数设置,命令运行过程中会以红字今天提醒,按照提醒对命令进行调整即可

如果有多个插件需要启用

--plugin-enable=numpy  --plugin-enable=qt-plugins  --plugin-enable=tensorflow

可以使用 nuitka --plugin-list查看可用的插件

C:\Users\Administrator\Desktop\a>nuitka  --plugin-list

        The following optional standard plugins are available in Nuitka

--------------------------------------------------------------------------------

data-files

dill-compat

enum-compat

eventlet          Required by the eventlet package

gevent            Required by the gevent package

implicit-imports

multiprocessing  Required by Python's multiprocessing module

numpy            Required for numpy, scipy, pandas, matplotlib, etc.

pbr-compat

pmw-freezer      Required by the Pmw package

pylint-warnings  Support PyLint / PyDev linting source markers

qt-plugins        Required by the PyQt and PySide packages

tensorflow        Required by the tensorflow package

tk-inter          Required by Python's Tk modules

torch            Required by the torch / torchvision packages

参数Output choices

-o FILENAME

指定生成的可执行文件的文件名,但是生成pyd的时候无法使用,也就是在使用--module的时候无法为pyd文件指定一个其他的文件名

--output-dir=DIRECTORY

指定打包好的文件存放的目录,默认为当前目录

--remove-output

使用nuitka进行打包的过程中,会生成一个用于build的中间临时目录,若可以使用该参数,命令完成后会自动删除build目录

--no-pyi-file

不生成pyi文件。pyi文件主要用于生成pyd文件时进行隐式import的检测

参数--show-progress 和--show-scons

用来显示详细打包过程,看得懂的话就加上吧,这部分还有几个参数,感兴趣的可以试试

    --show-scons        Operate Scons in non-quiet mode, showing the executed

                        commands. Defaults to off.

    --show-progress    Provide progress information and statistics. Defaults

                        to off.

    --show-memory      Provide memory information and statistics. Defaults to

                        off.

    --show-modules      Provide a final summary on included modules. Defaults

                        to off.

    --verbose          Output details of actions taken, esp. in

                        optimizations. Can become a lot. Defaults to off.

数 --windows-disable-console

禁用终端窗口,当程序有一个图形化界面的时候经常用到,仅限windows系统

参数 --windows-icon=ICON_PATH

设定程序的图标,仅限windows系统

----------------------------------------------------------- 深水区警告 --------------------------------------------------------------------

对反射的支持

python的反射机制,简而言之,就是可以通过字符串,动态调用一些库或者模块,诸如根据用户的输入调用插件等。

pack_name=input("input the package name:")

pack=__import__(pack_name)

上面这种情况,pack到底是哪个库,完全依赖于用户输入,nuitka没法利用follow import这部分参数确定可能会被用到的库。这种情况下可以不对这些库进行打包,那么打包好的exe只要在搜索路径中能够找到这些库,程序依然可以正常运行。

但如果希望能够将这些模块打包为二进制(exe或者pyd),那么就要用到--include这部分参数

nuitka --follow-imports --include-package=testPackage mx.py

nuitka就会将这个package强行打包进exe,如果运行的时需要进行调用,程序就会在exe里面进行寻找,看看有没有这个package

include部分有四个具体的参数

指定一个package

--include-package=PACKAGE

指定一个module

--include-module=MODULE

指定一个目录,里面包含的所有包/模块都会被打包(覆盖其他递归选项)

--include-plugin-directory=MODULE/PACKAGE

与pattern匹配的所有文件都会被打包(覆盖其他递归选项)

--include-plugin-files=PATTERN

使用参数--module打包生成pyd文件

使用--module参数,将包/模块打包为二进制的pyd文件。module在这里可能会有点歧义,实际上借助--include参数,对于包/模块/目录(package/module/directory),都能打包为pyd。

打包一个package

nuitka --module --include-package=PACKAGE  PACKAGE 

打包一个module

nuitka --module --include-module=MODULE    MODULE

打包一个目录

nuitka --module --include-plugin-directory=DIRECTORY    DIRECTORY

打包一堆零散文件,与pattern匹配的所有文件都会被打包

nuitka --module --include-plugin-files=PATTERN    mods

打包pyd文件,必须借助--include参数,这是因为打包pyd的时候没有入口文件,所以就没有import可以follow,因此就必须要用到include对整个包进行指定,否则打包出来的pyd文件里面不会有任何的内容,引用这个pyd文件会提示找不到模块

ps:打包pyd过程中如果出现类似警告提示

Nuitka:WARNING:Recursed to package 'TestPackage' at 'C:\Users\Administrator\Desktop\a\TestPackage' twice.

作者说不用管,原话如下

I think this one is actually described in the user manual.

We compile the filename you give as a module, even if it is a package, giving an empty package. Then you get to force inclusion of a whole module, which makes it see the top level twice, ignoring it, which triggers the warning.

常见错误

(逐渐添加)

**ImportError: DLL load failed while importing xxxxx: %1 is not a valid Win32 application.**

加载pyd模块时发生

原因:vscode没有正确初始化

解决方法:直接在终端中运行python

编译模块时候发生

ImportError: dynamic module does not define module export function (PyInit_TestPackage2)

原因:使用参数--module编译出来的pyd文件,不能更改文件名

处理机制。


编译过程需联网添加部份组件,建议挂上梯子,网址可能被墙掉的,编译过程大概率卡在下载

winlibs-x86_64-posix-seh-gcc-11.3.0-llvm-14.0.3-mingw-w64msvcrt-10.0.0-r3.zip

组件,复制该网址自行下载提示无效的,需自行下载

下载

下载后参考cmd里面提示的路径把压缩包里的目录提取到类拟

Nuitka\Nuitka\Cache\downloads\gcc\x86_64\11.3.0-14.0.3-10.0.0-msvcrt-r3

这样的路径下,然后强行关掉cmd再重新编译,除这个外其它的组件都能顺利下载,编译后py文件同级目录下多了两个目录,其中带dist里的exe就是执行文件,把该目录复制就可以独立使用exe文件了。


nuitka参数列表

输入nuitka,回车之后会显示nuitka的参数列表

Usage: __main__.py [--module] [--run] [options] main_module.py

Options:

  --version            show program's version number and exit

  -h, --help            show this help message and exit

  --module              Create an extension module executable instead of a

                        program. Defaults to off.

  --standalone          Enable standalone mode in build. This allows you to

                        transfer the created binary to other machines without

                        it relying on an existing Python installation. It

                        implies these option: "--recurse-all". You may also

                        want to use "--python-flag=no_site" to avoid the

                        "site.py" module, which can save a lot of code

                        dependencies. Defaults to off.

  --python-arch=PYTHON_ARCH

                        Architecture of Python to use. One of "x86" or

                        "x86_64". Defaults to what you run Nuitka with

                        (currently "x86_64").

  --python-debug        Use debug version or not. Default uses what you are

                        using to run Nuitka, most likely a non-debug version.

  --python-flag=PYTHON_FLAGS

                        Python flags to use. Default uses what you are using

                        to run Nuitka, this enforces a specific mode. These

                        are options that also exist to standard Python

                        executable. Currently supported: "-S" (alias

                        "nosite"), "static_hashes" (do not use hash

                        randomization), "no_warnings" (do not give Python

                        runtime warnings), "-O" (alias "noasserts"). Default

                        empty.

  --python-for-scons=PYTHON_SCONS

                        If using Python3.3 or Python3.4, provide the path of a

                        Python binary to use for Scons. Otherwise Nuitka can

                        use what you run Nuitka with or a "scons" binary that

                        is found in PATH, or a Python installation from

                        Windows registry.

  --warn-implicit-exceptions

                        Enable warnings for implicit exceptions detected at

                        compile time.

  --warn-unusual-code  Enable warnings for unusual code detected at compile

                        time.

  --assume-yes-for-downloads

                        Allow Nuitka to download code if necessary, e.g.

                        dependency walker on Windows.

  Control the inclusion of modules and packages:

    --include-package=PACKAGE

                        Include a whole package. Give as a Python namespace,

                        e.g. ``some_package.sub_package`` and Nuitka will then

                        find it and include it and all the modules found below

                        that disk location in the binary or extension module

                        it creates, and make it available for import by the

                        code. Default empty.

    --include-module=MODULE

                        Include a single module. Give as a Python namespace,

                        e.g. ``some_package.some_module`` and Nuitka will then

                        find it and include it in the binary or extension

                        module it creates, and make it available for import by

                        the code. Default empty.

    --include-plugin-directory=MODULE/PACKAGE

                        Include the content of that directory, no matter if

                        it's used by the given main program in a visible form.

                        Overrides all other recursion options. Can be given

                        multiple times. Default empty.

    --include-plugin-files=PATTERN

                        Include into files matching the PATTERN. Overrides all

                        recursion other options. Can be given multiple times.

                        Default empty.

  Control the recursion into imported modules:

    --follow-stdlib, --recurse-stdlib

                        Also descend into imported modules from standard

                        library. This will increase the compilation time by a

                        lot. Defaults to off.

    --nofollow-imports, --recurse-none

                        When --recurse-none is used, do not descend into any

                        imported modules at all, overrides all other recursion

                        options. Defaults to off.

    --follow-imports, --recurse-all

                        When --recurse-all is used, attempt to descend into

                        all imported modules. Defaults to off.

    --follow-import-to=MODULE/PACKAGE, --recurse-to=MODULE/PACKAGE

                        Recurse to that module, or if a package, to the whole

                        package. Can be given multiple times. Default empty.

    --nofollow-import-to=MODULE/PACKAGE, --recurse-not-to=MODULE/PACKAGE

                        Do not recurse to that module name, or if a package

                        name, to the whole package in any case, overrides all

                        other options. Can be given multiple times. Default

                        empty.

  Immediate execution after compilation:

    --run              Execute immediately the created binary (or import the

                        compiled module). Defaults to off.

    --debugger, --gdb  Execute inside "gdb" to automatically get a stack

                        trace. Defaults to off.

    --execute-with-pythonpath

                        When immediately executing the created binary

                        (--execute), don't reset PYTHONPATH. When all modules

                        are successfully included, you ought to not need

                        PYTHONPATH anymore.

  Dump options for internal tree:

    --xml              Dump the final result of optimization as XML, then

                        exit.

  Code generation choices:

    --full-compat      Enforce absolute compatibility with CPython. Do not

                        even allow minor deviations from CPython behavior,

                        e.g. not having better tracebacks or exception

                        messages which are not really incompatible, but only

                        different. This is intended for tests only and should

                        not be used for normal use.

    --file-reference-choice=FILE_REFERENCE_MODE

                        Select what value "__file__" is going to be. With

                        "runtime" (default for standalone binary mode and

                        module mode), the created binaries and modules, use

                        the location of themselves to deduct the value of

                        "__file__". Included packages pretend to be in

                        directories below that location. This allows you to

                        include data files in deployments. If you merely seek

                        acceleration, it's better for you to use the

                        "original" value, where the source files location will

                        be used. With "frozen" a notation "<frozen

                        module_name>" is used. For compatibility reasons, the

                        "__file__" value will always have ".py" suffix

                        independent of what it really is.

  Output choices:

    -o FILENAME        Specify how the executable should be named. For

                        extension modules there is no choice, also not for

                        standalone mode and using it will be an error. This

                        may include path information that needs to exist

                        though. Defaults to <program_name> on this platform.

                        .exe

    --output-dir=DIRECTORY

                        Specify where intermediate and final output files

                        should be put. The DIRECTORY will be populated with C

                        files, object files, etc. Defaults to current

                        directory.

    --remove-output    Removes the build directory after producing the module

                        or exe file. Defaults to off.

    --no-pyi-file      Do not create a ".pyi" file for extension modules

                        created by Nuitka. This is used to detect implicit

                        imports. Defaults to off.

  Debug features:

    --debug            Executing all self checks possible to find errors in

                        Nuitka, do not use for production. Defaults to off.

    --unstripped        Keep debug info in the resulting object file for

                        better debugger interaction. Defaults to off.

    --profile          Enable vmprof based profiling of time spent. Not

                        working currently. Defaults to off.

    --graph            Create graph of optimization process. Defaults to off.

    --trace-execution  Traced execution output, output the line of code

                        before executing it. Defaults to off.

    --recompile-c-only  This is not incremental compilation, but for Nuitka

                        development only. Takes existing files and simply

                        compile them as C again. Allows compiling edited C

                        files for quick debugging changes to the generated

                        source, e.g. to see if code is passed by, values

                        output, etc, Defaults to off. Depends on compiling

                        Python source to determine which files it should look

                        at.

    --generate-c-only  Generate only C source code, and do not compile it to

                        binary or module. This is for debugging and code

                        coverage analysis that doesn't waste CPU. Defaults to

                        off. Do not think you can use this directly.

    --experimental=EXPERIMENTAL

                        Use features declared as 'experimental'. May have no

                        effect if no experimental features are present in the

                        code. Uses secret tags (check source) per experimented

                        feature.

    --disable-dll-dependency-cache

                        Disable the dependency walker cache. Will result in

                        much longer times to create the distribution folder,

                        but might be used in case the cache is suspect to

                        cause errors.

    --force-dll-dependency-cache-update

                        For an update of the dependency walker cache. Will

                        result in much longer times to create the distribution

                        folder, but might be used in case the cache is suspect

                        to cause errors or known to need an update.

  Backend C compiler choice:

    --clang            Enforce the use of clang. On Windows this requires a

                        working Visual Studio version to piggy back. Defaults

                        to off.

    --mingw64          Enforce the use of MinGW64 on Windows. Defaults to

                        off.

    --msvc=MSVC        Enforce the use of specific MSVC version on Windows.

                        Allowed values are e.g. 14.0, specify an illegal value

                        for a list of installed compilers.  Defaults to the

                        most recent version.

    -j N, --jobs=N      Specify the allowed number of parallel C compiler

                        jobs. Defaults to the system CPU count.

    --lto              Use link time optimizations if available and usable

                        (gcc 4.6 and higher). Defaults to off.

  Tracing features:

    --show-scons        Operate Scons in non-quiet mode, showing the executed

                        commands. Defaults to off.

    --show-progress    Provide progress information and statistics. Defaults

                        to off.

    --show-memory      Provide memory information and statistics. Defaults to

                        off.

    --show-modules      Provide a final summary on included modules. Defaults

                        to off.

    --verbose          Output details of actions taken, esp. in

                        optimizations. Can become a lot. Defaults to off.

  Windows specific controls:

    --windows-dependency-tool=DEPENDENCY_TOOL

                        When compiling for Windows, use this dependency tool.

                        Defaults to depends.exe, other allowed value is

                        'pefile'.

    --windows-disable-console

                        When compiling for Windows, disable the console

                        window. Defaults to off.

    --windows-icon=ICON_PATH

                        Add executable icon (Windows only).

  Plugin control:

    --plugin-enable=PLUGINS_ENABLED, --enable-plugin=PLUGINS_ENABLED

                        Enabled plugins. Must be plug-in names. Use --plugin-

                        list to query the full list and exit. Default empty.

    --plugin-disable=PLUGINS_DISABLED, --disable-plugin=PLUGINS_DISABLED

                        Disabled plugins. Must be plug-in names. Use --plugin-

                        list to query the full list and exit. Default empty.

    --plugin-no-detection

                        Plugins can detect if they might be used, and the you

                        can disable the warning via --plugin-disable=plugin-

                        that-warned, or you can use this option to disable the

                        mechanism entirely, which also speeds up compilation

                        slightly of course as this detection code is run in

                        vain once you are certain of which plug-ins to use.

                        Defaults to off.

    --plugin-list      Show list of all available plugins and exit. Defaults

                        to off.

    --user-plugin=USER_PLUGINS

                        The file name of user plugin. Can be given multiple

                        times. Default empty.


python库版本信息查询

Archived: Python Extension Packages for Windows - Christoph Gohlke (uci.edu)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容