How to get pubsub to work with pyinstaller? - python

I'm trying to use pyinstaller to build an exe from my python code. One of the modules I'm using is pubsub (pypubsub really. It used to be a part of wxpython). I'm getting errors when I try to run the exe. It complains "ImportError: No module named listenerimpl".
I've seen some articles about getting wx.lib.pubsub to work (it has known issues with pyinstaller). I've tried the solutions presented in those articles (slightly modified to account for it not being a part of wx anymore) but no luck.
I can get past the initial "ImportError: No module named listenerimpl" error by adding the path to the right listenerimpl (the kwargs one) to the list of files for Analysis in my spec file but then I hit further errors on importing "publisher". That error isn't fixed by adding its path in the spec file.
I think the solution shouldn't involve adding the path to listenerimpl.py in my spec file... but I'm not sure how to get this working happily.
extra info
using pubsub version: 3.1.1b1.201005.r243
using pyinstaller version: 2.0
platform: win7

pubsub problems solved (although exe still not running).
So if you look at comments here (especially comment #15 by sebastian.hilbert) it mostly solves the problems with some tweaking.
The necessary tweaks.
Change the names on the hook files to hook-pubsub.core.py and hook-pubsub.setuparg1.py.
Internal to those files you should get rid of references to wx.
Enable the hook files. You can do this one of two ways. The easy way is to drop these new hook files into 'pyinstaller-2.0\PyInstaller\hooks' which is where pyinstaller looks for hooks by default. The clean/nice way to do this is to put these hooks into their own folder and add that folder as hookspath in your spec file.
NB: It was not clear to me how to add a hookspath. In your specfile, in the call to Analyze, there is a hookspath arg. It wants a list not a string. So you want to do something like hookspath=['path1', 'path2', etc].
NB2: Additionally if you ask for "path.dirname(path.abspath(__file__))" you will get the directory for pyinstaller not the location where your spec file lives.

For those coming in late to this like myself, there's a new recommended procedure.
I recommend using oliver's PyPubSub. For Python 2.7, use his 3.4.2 release. Make sure you're only using this PubSub. This means if you have any other PubSub's in your env/lib/site-packages - not counting the one bundled with wxPython - you'll want to get rid of them. They WILL cause problems.
Despite what you may have read, do not use from pubsub import setupkwargs.
Don't add any new hooks to PyInstaller. They've already got it covered.
That's it. You're done.
Run PyInstaller. Check for any bugs in the build. Hopefully, PubSub won't be one of them.

Related

Is there a way to import a .pyd extension file as a simple include in a python file?

Hi there wise people of stack. I'm having trouble with importing pyd files as python objects.
The story:
I have an internal repo on gitlab that runs python files as well as C++ files. the repo uses pybind for both languages to speak to one another. The whole project is built with CI/CD and the artefact I have access to are .pyd extension files.
What I was given as a task would be to access some .pyd files (in different folders) with a single python script and access their classes (encoded inside this .pyd file) to mock them using python.
The problem:
What I was told was that I would need a simple include to be able to access the .pyd as an object through python just like you would with a library. However, I came across errors in the whole process. I have gone through this post and this one, but it seems that none of them works for me.
What was tried:
The first thing I did was start a remote folder with a single .pyd file from the project(let's call it SomeClass.pyd). I then created a python file test.py in the same directory as the pyd file.
The whole architecture looks like the following:
|--folder
|--SomeClass.pyd
|--test.py
Then, in the test.py file, I tried running
import SomeClass.pyd
import SomeClass
import SomeClass.pyd as sc
from SomeClass.pyd import *
from SomeClass import *
which all yielded the same following error:
ImportError: dynamic module does not define module export function
Now, I know that pyd files are similar to dlls, but I was told multiple time that a simple import would let me access the object information without needing anything in particular.
I recall reading about adding the PYTHONPATH before launching the whole process. However, I need that file to access the pyd without having to add any variable to the path as I will likely not always have access rights to the PYTHONPATH.
The project is quite big, so I'm trying to keep it bare minimum, but if you need more info, I'll try to give some more.
Thank you for your feedback!
Alright, after some time and a lot of researching, I found the weird answer for the problem that occured. I really hope it will help anyone encountering the same issue.
The problem was caused by the fact that pycharm has sometimes issues with the whole dynamic import.
First problem: dynamic import
This was solved simply by going on pycharm --> files --> invalidate cache and then tick "Clear file system cache and Local History" as well as "Clear VCS Log caches and indexes". You should then be prompted to reboot.
I also add a note that even after fixing the issue, sometime, for no apparent reason, I still have to invalidate cache again.
Second problem: venv
Once rebooted, you might be able to import manually the path to your pyd file, but you probably won't be able to auto complete. What solved this for me was compiling manually the code responsible for the pyd in order to generate a wheel. In my case, I used poetry:
poetry build
Once the wheel was created, I did a manual pip install of the wheel created by the poetry build to install it directly into the venv:
pip install dist/the_name_of_your_wheel_file.whl
These steps were the ones to fix my problem. I hope this will help anyone encountering the same problem!

How to solve ModuleNotFoundError: No module named 'string' error in Python 3?

I was trying to add the Strings library into the Robot Framework Interpreter folder in PyCharm, where first it showed me error
Command errored out with exit status: 1
So, I googled out this issue first, and this link suggested me to delete 'strings.py' file from the libraries. I did so and now nothing is working.
Anything I do now, it shows error of "ModuleNotFoundError: No module named 'string'".
I could not even install string using
pip install strings
command.
Whatever I try to do with pip, now shows this error.
Can anyone please suggest me the solution for this?
I am using Python version 3.10.
Several notes:
The library in question is 9 years old, is not maintained, is known by the author to be buggy, was written as a joke, and does not contain anything useful. There is no good reason why you should be trying to install it for your project. If you think you need it for something, then you have some other misconception that needs to be cleared up.
The link you found did not tell you to delete strings.py from "the libraries". It said something about deleting string.py - notice, no s at the end - from a local project folder. The reason for this is because that name conflicts with the library name. The page author's own source file, named string.py, sought to import the standard library file string.py (as it clearly says import string in the screen shot), but it cannot - because it finds itself first. This is a common problem for new Python users.
DO NOT EVER MANUALLY EDIT THE CONTENTS OF YOUR INSTALLATION DIRECTORY ON THE ADVICE OF SOME RANDOM WEB PAGE.
Ideally, don't ever do it at all. That content is not intended to be touched. Installers exist for a reason. If for some incredibly specific reason you feel the need to do this, make sure you have backups of everything and that you are 100% sure you can restore everything to its initial state if anything goes wrong.
The person writing that web page was incorrect. The installation error had nothing to do with the string.py file.
The actual cause of the problem is that the package is broken and cannot be installed properly on anyone else's machine. Again, this is no big loss as there is no use for the package anyway.
The reason it is broken is that the setup script for the package tries to import the code that's being installed, in order to get version and author information. This seems to work locally, but fails for everyone else.
To reiterate: the person writing that article wrote nonsense. (I'm not surprised; the page formatting is awful and the grammar isn't particularly great either.) Looking further, it appears that the entire website is authored by the one person, who is clearly just trying to self-promote (with a Youtube channel as well) while lacking the necessary expertise. Browsing around the rest of the site a bit, I see articles that are pedantic and not very insightful, and occasionally inaccurate - but all very SEO optimized.
I recommend ignoring that website entirely.
To reiterate: the string module comes with your Python. You cannot reinstall it with pip - not with the strings package you found, nor any other package. Your options are:
Find the correct string.py contents (possibly from a backup, assuming you thought to make a backup before deleting something from an installation directory) and restore them. This is the official repository for the reference implementation of Python. You might be able to find it in there somewhere. I don't recommend trying. There is a lot to go through and it is possible to damage things further.
Reinstall Python completely.
The error that you are getting is because you deleted the string.py file. There is no string module to be imported from PyPi. This is why pip install string doesn't work. Restore the deleted file as it is not the cause of your problem.
If you try to install Strings library it will fail because you are using Python 3.10 and the Strings library that you want to import and install is quite old and not supported for this Python version. Therefore you get the ModuleNotFoundError: No module named 'strings' that you see in the link that you attached.
For the setup.py file from the library I see that it recommends using Python 3.3, so I will recommend you to use that version of Python if you want to use this specific library.
Please note that the link that you provided is probably in case that you have created your own string.py file.
I solved this question by deleting any __pycache__ folder in the project directory.

Building python 3.6.6 from source on Win10

I've downloaded the python 3.6.6 source from here...
https://www.python.org/downloads/release/python-366/
...and followed the instruction on how to build on Windows (run ../PCbuild/build.bat). Python compiles and seems to be working (funny and scary: while fetching externals, it actually downloads python-3.7.0 as a dependency... :/ ). However, it looks like the build is somehow 'in place', and the binaries end up in some sub-folder of the source (../PCbuild/amd64/python.exe). This means I'm left with source and compiled code mixed up instead of some clean/lean and deployable package.
can I somehow provide '--prefix=/target/build/path' to define a target location to build to, like I would on linux?
is there a way of removing all src files/folders and leave only the required files/folders (../lib, ../include, etc...).
Or in general, is there a way of making the build process more behave like on linux?
Thanks for your help,
Max
The build.bat from PCBuild is intended for developers, that is, for testing purposes. What you want is under \Tools\msi\buildrelease.bat. This creates a subdirectory under \PCBuild\ that places all msi, cab and exe files ready for later installation. According to the readme, there doesn't seem to be an option to pack all those files in a single .exe file, like all installers eventually do, but another option is under \Tools\msi\build.bat which does have an option for packing (namely build.bat --pack). "But", the readme does state that the buildrelease.bat should be used for an official release. The advantage of doing so is that Pyhton would be optimized using PGO to your own hardware. I am also trying to compile from source using this method but I am having an issue with a recurring error (and other ones):
PGO run did not succeed (no python36!*.pgc files) and there is no data to merge [E:\RepoGiT\3.6\PCbuild\pythoncore.vcxproj]
so, if you do go this route, and find this, or other errors, please send the bug report to python's bug tracker webpage. And better yet, if you find errors and their solution, please report back here!

How do I download a 3rd party python module and integrate it with my python

I would like to be able to use the services that the Blockcypher module provides for my programme, however i have (at least i think) downloaded the correct module package but cant get it to integrate with my Python on my Computer. I am fairly new to python so I have no idea on where to even start tackling this problem.
Modules, regardless of where you've got hold of them, will be searched for in the sys.path. If nothing is found there, they will be looked up in the current directory.
When you download some code directly it will be a good first guess to place it in the directory of the script from where you are using the download. If it's just a .py-file, place it there. If it's an archive with a directory, then place the directory there (not the files).
Generally, you should prefer installing modules via a package manager such as pip or conda. Such package managers take care of placing modules properly for usage with your Python installation from wherever you will write your script. They also provide support for updating these modules to newer versions later.
Update: If you cannot make anything from this remarks, you should first read the section on modules in the Python tutorial, or even work thru the full tutorial or thru a good book (or any other ;) to get a smooth entry into the friendly world of Python programming.
Update (2023): The Dive Into Python link above is outdated, so here is the updated link to this great resource:
https://diveintopython3.problemsolving.io
I think it's still the best beginner's resource, but, well, here are many more:
https://wiki.python.org/moin/IntroductoryBooks

Py2App Can't find standard modules

I've created an app using py2app, which works fine, but if I zip/unzip it, the newly unzipped version can't access standard python modules like traceback, or os. The manpage for zip claims that it preserves resource forks, and I've seen other applications packaged this way (I need to be able to put this in a .zip file). How do I fix this?
This is caused by building a semi-standalone version that contains symlinks to the natively installed files and as you say, the links are lost when zipping/unzipping unless the "-y" option is used.
An alternate solution is to build for standalone instead, which puts (public domain) files inside the application and so survives zipping/unzipping etc. better. It also means the app is more resilient to changes in the underlying OS. The downside is that it is bigger, of course, and is more complicated to get it set up.
To build a stand alone version, you need to install the python.org version which can be repackaged.
An explanation of how to do this is here, but read the comments as there have been some changes since the blog post was written.
use zip -y ... to create the file whilst preserving symlinks.
You probably need to give it your full PYTHONPATH.
Depends on your os. Here's how to find out:
import os [or any other std module]
os.file()

Categories