PyInstaller does NOT work when including Pysnmp

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

Just trying one of the official documentation site examples:

from pysnmp.hlapi import *  errorIndication, errorStatus, errorIndex, varBinds = next(     getCmd(SnmpEngine(),           CommunityData('public'),           UdpTransportTarget(('192.168.1.14', 161)),           ContextData(),           ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) )  if errorIndication:     print(errorIndication) elif errorStatus:     print('%s at %s' % (            errorStatus.prettyPrint(),            errorIndex and varBinds[int(errorIndex)-1][0] or '?'        )     ) else:     for varBind in varBinds:        print(' = '.join([ x.prettyPrint() for x in varBind ])) 

we can see it does work if its executed through the Python interpreter:

 (Compiler)[user@machine testSNMP]$ python testSNMP.py   SNMPv2-MIB::sysDescr."0" = 48-port 10/100/1000 Gigabit Switch 

However, if I try to "freeze" it with PyInstaller (PyInstaller --onefile) I get the following error once it is executed:

  (Compiler)[user@machine testSNMP]$ /lab/testSNMP/dist/testSNMP Traceback (most recent call last):   File "", line 4, in    File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.entity.engine", line 83, in __init__   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.smi.builder", line 359, in importSymbols pysnmp.smi.error.MibNotFoundError: No module __SNMP-FRAMEWORK-MIB loaded at 

It seems that mandatory files in pysnmp/smi/mibs are not explicitly imported to be used. That's why I've split the build procedure in phases. Fist, create the spec file.

(Compiler)[user@machine testSNMP]$ pyi-makespec --onefile getInterfaces.py wrote /lab/testSNMP/getInterfaces.spec now run pyinstaller.py to build the executable 

Then, I've edited it to import required files following advices from this other stack post (Can't get pysnmp to work with pyinstaller):

# -*- mode: python -*- import PyInstaller.hooks.hookutils hiddenimports = ['pysnmp.smi.exval','pysnmp.cache'] + PyInstaller.hooks.hookutils.collect_submodules('pysnmp.smi.mibs') + PyInstaller.hooks.hookutils.collect_submodules('pysnmp.smi.mibs.instances') a = Analysis(['testSNMP.py'],             pathex=['/lab/testSNMP'],             hiddenimports=hiddenimports,             hookspath=None,             runtime_hooks=None) x = Tree('/virtualenvs/Compiler/lib/python2.7/site-packages/pysnmp/smi/mibs',prefix='pysnmp/smi/mibs',excludes='.py') pyz = PYZ(a.pure) exe = EXE(pyz,          a.scripts,          a.binaries,          a.zipfiles,          a.datas,          x,          name='testSNMP',          debug=False,          strip=None,          upx=True,          console=True ) 

But then, once it's built and executed, I'm getting this other error:

(Compiler)[user@machine testSNMP]$ /lab/testSNMP/dist/testSNMP Traceback (most recent call last):   File "", line 15, in    File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.hlapi.asyncore.sync.cmdgen", line 98, in getCmd   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.hlapi.asyncore.cmdgen", line 135, in getCmd   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.hlapi.varbinds", line 30, in makeVarBinds   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.smi.rfc1902", line 689, in resolveWithMib   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.smi.rfc1902", line 299, in resolveWithMib   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysnmp.smi.compiler", line 44, in addMibCompiler   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysmi.parser.smi", line 21, in __init__   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysmi.lexer.smi", line 83, in __init__   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/pysmi.lexer.smi", line 100, in reset   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/ply.lex", line 915, in lex   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/ply.lex", line 577, in validate_all   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/ply.lex", line 819, in validate_rules   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/ply.lex", line 830, in validate_module   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/inspect", line 690, in getsourcelines   File "/lab/testSNMP/build/testSNMP/out00-PYZ.pyz/inspect", line 538, in findsource IOError: could not get source code 

What else can I do? Thanks in advance!

回答1:

I had the same problem and managed to get it working by including the pysmi files as a Tree just like the pysnmp mibs.

My pyinstaller spec file ended up like:

...  x = Tree(os.getcwd()+'/.pyenv/Lib/site-packages/pysnmp/smi/mibs',prefix='pysnmp/smi/mibs') y = Tree(os.getcwd()+'/.pyenv/Lib/site-packages/pysmi',prefix='pysmi')  ...  exe = EXE(pyz,       a.scripts,       a.binaries,       a.zipfiles,       a.datas,       x,y,  ... 

While this worked I actually solved it in another way by using an older version of pysnmp v4.2.5 which doesn't depend on pysmi



回答2:

Got the same error "could not get source code". There is an issue about that created on Pyinstaller github page: https://github.com/pyinstaller/pyinstaller/issues/1945 Solution is to include ply to spec file as it is described in link you mentioned: Can't get pysnmp to work with pyinstaller by adding "PyInstaller.utils.hooks.collect_submodules('ply')" to hiddenimports

And make sure ply version is >= 3.9!

My spec file looks pretty much same except Analysis part:

a = Analysis(['main.py'],          binaries=None,          datas=PyInstaller.utils.hooks.collect_data_files('pysnmp') + \          hiddenimports=PyInstaller.utils.hooks.collect_submodules('pysmi')+\          PyInstaller.utils.hooks.collect_submodules('ply') + \          PyInstaller.utils.hooks.collect_submodules('pyasn1') + \          PyInstaller.utils.hooks.collect_submodules('pysnmp'),          hookspath=None,          runtime_hooks=None,          excludes=None,          win_no_prefer_redirects=None,          win_private_assemblies=None,          cipher=block_cipher) 


回答3:

To make Jeremy's answer portable, you can modify your specfile like this diff:

+ import os.path + import pysmi + import pysnmp.smi.mibs  + def module_base(module): +   return os.path.abspath(os.path.join(module.__file__, os.pardir))    coll = COLLECT(       exe,       a.binaries,       a.zipfiles,       a.datas, +     Tree(module_base(pysmi), prefix='pysmi'), +     Tree(module_base(pysnmp.smi.mibs), prefix='pysnmp/smi/mibs'),       ... 

EDIT: turn out adding these to hiddenimports solved the problem for me:

'pysnmp.smi.mibs', 'pysnmp.smi.mibs.instances', 'pysnmp.smi.exval', 'pysnmp.cache' 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!