【问题标题】:nameko http micro service run fail with cyphon compiled pyd file but py file wellnameko http 微服务运行失败,cyphon 编译 pyd 文件但 py 文件很好
【发布时间】:2022-01-06 06:16:41
【问题描述】:

我开发了一个nameko http微服务,可以正常运行,但是如果我把文件myhttp.py替换成cyphon编译的文件myhttp.py,就会得到[curl: (7) Failed to connect to localhost端口 8000:连接被拒绝],请帮帮我。

第一步:使用以下3个文件(build.bat,setup.py,myhttp.py)生成myhttp.pyd

build.bat

python setup.py build_ext --inplace

setup.py

from setuptools import setup
from Cython.Build import cythonize

setup(
    name = 'myapp',
    ext_modules=cythonize("myhttp.py"),
    zip_safe=False,
)

我的http.py

from nameko.web.handlers import http
import json
class MyHttpService:
    name = 'my_http_service'
    
    @http('POST','/hello')  #curl -i -d "world" localhost:8000/hello
    def hello(self, request):
        return "Hello, {}!".format(request.get_data(as_text=True))
    
    

第二步:使用下面3个文件(installer.bat、namekorun.py、namekorun.spec)和刚才生成的myhttp.pyd生成namekorun.exe

installer.bat

pyinstaller --noconfirm namekorun.spec

namekorun.py

import eventlet; 
eventlet.monkey_patch()
from nameko.runners import ServiceRunner
import myhttp
import signal


runner = ServiceRunner(config={'WEB_SERVER_ADDRESS': '0.0.0.0:8000'})
runner.add_service(myhttp.MyHttpService)


def shutdown(signum, frame):
    # signal handlers are run by the MAINLOOP and cannot use eventlet
    # primitives, so we have to call `stop` in a greenlet
    eventlet.spawn_n(runner.stop)

signal.signal(signal.SIGTERM, shutdown)
runner.start()
runnlet = eventlet.spawn(runner.wait)
while True:
    try:
        runnlet.wait()
    except OSError as exc:
        if exc.errno == errno.EINTR:
            # this is the OSError(4) caused by the signalhandler.
            # ignore and go back to waiting on the runner
            continue
        raise
    except KeyboardInterrupt:
        print()  # looks nicer with the ^C e.g. bash prints in the terminal
        try:
            runner.stop()
        except KeyboardInterrupt:
            print()  # as above
            runner.kill()
    else:
        # runner.wait completed
        break
    
    
    

namekorun.spec

   # -*- mode: python ; coding: utf-8 -*-
    
    
    block_cipher = None
    
    
    partylibs = ['nameko.constants','nameko.containers','nameko.contextdata','nameko.dependency_providers','nameko.events','nameko.exceptions','nameko.extensions','nameko.log_helpers','nameko.messaging','nameko.rpc','nameko.runners','nameko.serialization','nameko.timer','nameko.amqp.publish','nameko.cli.actions','nameko.cli.backdoor','nameko.cli.code','nameko.cli.commands','nameko.cli.main','nameko.cli.run','nameko.cli.shell','nameko.cli.show_config','nameko.standalone.events','nameko.standalone.rpc','nameko.testing.pytest','nameko.testing.rabbit','nameko.testing.services','nameko.testing.utils','nameko.testing.waiting','nameko.testing.websocket','nameko.utils.retry','nameko.utils.concurrency','nameko.web.handlers','nameko.web.server','nameko.web.websocket']
    
    partylibs += ['eventlet','eventlet.hubs.epolls','eventlet.hubs.kqueue','eventlet.hubs.selects']
    partylibs += ['dns','dns.dnssec','dns.e164','dns.hash','dns.namedict','dns.tsigkeyring','dns.update','dns.version','dns.zone']
    
    a = Analysis(['namekorun.py'],
                 pathex=[],
                 binaries=[],
                 datas=[],
                 hiddenimports=partylibs,
                 hookspath=[],
                 hooksconfig={},
                 runtime_hooks=[],
                 excludes=[],
                 win_no_prefer_redirects=False,
                 win_private_assemblies=False,
                 cipher=block_cipher,
                 noarchive=False)
    pyz = PYZ(a.pure, a.zipped_data,
                 cipher=block_cipher)
    
    exe = EXE(pyz,
              a.scripts, 
              [],
              exclude_binaries=True,
              name='namekorun',
              debug=False,
              bootloader_ignore_signals=False,
              strip=False,
              upx=True,
              console=True,
              disable_windowed_traceback=False,
              target_arch=None,
              codesign_identity=None,
              entitlements_file=None )
    coll = COLLECT(exe,
                   a.binaries,
                   a.zipfiles,
                   a.datas, 
                   strip=False,
                   upx=True,
                   upx_exclude=[],
                   name='namekorun')
           

第 3 步:启动 dist/namekorun/namekorun.exe,然后在命令中输入 curl -i -d "world" localhost:8000/hello 窗口,并得到 curl: (7) 无法连接到localhost 8000端口:连接被拒绝如果用myhttp.py替换myhttp.pyd,它运行良好

我的包如下,使用 vs2015

Package Version
python 3.6.8
Cython 3.0.0a9
decorator 4.4.2
eventlet 0.25.1
kombu 4.6.8
nameko 2.12.0
pyinstaller 4.7
pyinstaller-hooks-contrib 2021.4

【问题讨论】:

  • 我认为您可以简化一下。 Pyinstaller 步骤对于这个问题实际上是必要的吗?如果直接从 Python 运行,它可以工作吗?
  • @DavidW 我刚试了一下。它不起作用,在编译成pyd(Linux 上的.so)之后。并将日志级别设置为DEBUG,但它什么时候做都不显示curl 被拒绝了。
  • 如果myhttp.py不是由cython编译的,只需在hello方法中调用其他部分(由cython编译,演示函数)就可以正常工作。@过程中的任何错误987654336@注册函数,byhttp装饰器?
  • 也感谢浩岚!为了您的耐心,请重现我的错误。

标签: pyinstaller cython nameko


【解决方案1】:

追溯nameko.web.handlers.http的定义:

setattr(fn, ENTRYPOINT_EXTENSIONS_ATTR, descriptors)

本质上它是在尝试在函数对象上设置属性。 Cython 函数是与常规 Python 函数不同的类,并且该类没有实例字典,因此 setattr 将失败(我有点惊讶您没有收到明显的错误)。

因此,我不希望使用 Cython 编译此代码。

【讨论】:

  • 再次感谢 DavidW!让我知道这种方法是不可行的。我将放弃编译myhttp.py。其实我的目的是隐藏python源代码,因为大部分文件都编译成功了,不编译文件没什么大不了的。我已经完成了我的任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多