py2exe is giving errors on my os.listdir code - python

When I run my code from main, it runs perfectly fine, but when I try to build main into an exe using py2exe, it gives this error:
Traceback (most recent call last):
File "main.py", line 118, in <module>
menu.menu.Menu()
File "menu\menu.pyo", line 20, in __init__
File "settingsManager.pyo", line 61, in getSetting
File "settingsManager.pyo", line 148, in __init__
WindowsError: [Error 3] The system cannot find the path specified: 'C:\\Users\\digiholic\\git\\universalSmashSystem\\main.exe\\settings\\rules/*.*'
The line it's referring to is:
for f in os.listdir(os.path.join(os.path.dirname(__file__),'settings','rules')):
It looks like os.listdir is using unix file pathing to find every file, and Windows is having none of that. Is there a way to use listdir in a way that won't blow up everything?

When you're running within the exe you need to check if the module is frozen, the path from __file__ is generally not what you expect when you're within an exe vs the raw python script. You need to access the location with something like this:
import imp, os, sys
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
def get_main_dir():
if main_is_frozen():
return os.path.dirname(sys.executable)
return os.path.dirname(sys.argv[0])
Source: http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
You can also check another direction here: http://www.py2exe.org/index.cgi/WhereAmI

Related

Basic python error with importing module - getting modulenotfound error

I'm doing something basic with python, and I'm getting a pretty common error, but not able to find exactly what's wrong. I'm trying to use a custom module (built by someone else). I have the folder structure like this:
There is the test folder, and I have a file testing.py within that:
The contents of testing.py is:
from util import get_data, plot_data
fruits = ["apple", "banana", "cherry"]
for x in fruits:
print(x)
When I run this file, using python testing.py, I get this:
I went through the other questions that speak about paths, and this looks fine, so not sure what I am missing here. My environment is setup using conda, and the environment is active.
EDIT
As per #allan-wind, I made the relative edit, which got me past the error, but now getting different errors:
I tried the relative import, and it got past that error, but then it is now throwing this error:
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\envs\ml4t\lib\multiprocessing\context.py", line 190, in get_context
ctx = _concrete_contexts[method]
KeyError: 'fork'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "grade_analysis.py", line 21, in <module>
from grading.grading import (
File "E:\_Repo\GT\CS7646\mls4tsp23\grading\grading.py", line 15, in <module>
multiprocessing.set_start_method('fork')
File "C:\ProgramData\Anaconda3\envs\ml4t\lib\multiprocessing\context.py", line 246, in set_start_method
self._actual_context = self.get_context(method)
File "C:\ProgramData\Anaconda3\envs\ml4t\lib\multiprocessing\context.py", line 238, in get_context
return super().get_context(method)
File "C:\ProgramData\Anaconda3\envs\ml4t\lib\multiprocessing\context.py", line 192, in get_context
raise ValueError('cannot find context for %r' % method)
ValueError: cannot find context for 'fork'
`
There are a number of ways to specify how to find modules:
Use a relative import:
from .util import get_data, plot_data
Set the environment variable PYTHONPATH includes the directory where you module resides.
See sys.meta_path
Just place utils in the same folder as your testing.py and the python interpreter you put that directory in your path. Other solutions would be to place utils in a directory that is already in your path, since if thats not the case, you cant import from "above" the current directory

I am having an error on accessing a file from another directory with Python

This is my Python code:
from plugin import Plugin
import logging
import yaml
log = logging.getLogger('discord')
def get_bot_prefix():
with open('HarTex/hartexConfig.yaml', 'r') as prefixReader:
prefixValue = yaml.safe_load(prefixReader)
prefixString = prefixValue['settings']['prefix']
return prefixString
prefix = get_bot_prefix()
However I got an error with the file accessing:
Traceback (most recent call last):
File "C:/Users/85251/Documents/Discord Bots/Python/HarTex/bot.py", line 20, in <module>
from plugins.help import Help
File "C:\Users\85251\Documents\Discord Bots\Python\HarTex\plugins\help.py", line 30, in <module>
prefix = get_bot_prefix()
File "C:\Users\85251\Documents\Discord Bots\Python\HarTex\plugins\help.py", line 22, in get_bot_prefix
with open('HarTex/hartexConfig.yaml', 'r') as prefixReader:
FileNotFoundError: [Errno 2] No such file or directory: 'HarTex/hartexConfig.yaml'
How can I fix it? Or am I completely wrong with the directory?
The script should work if you are calling it from the parent directory of HarTex, maybe you are running it from a different working directory?
You could also try to open the file using the full path, as this is probably easy to check.
Error is very clear.You should use absolute path instead of relative path.
For an example home/Prakash/Desktop/test12/test.yaml
Your code definitely work,Once you will change path like this.

cx_freeze and docx - problems when freezing

I have a simple program that takes input from the user and then does scraping with selenium. Since the user doesn't have Python environment installed I would like to convert it to *.exe. I usually use cx_freeze for that and I have successfully converted .py programs to .exe. At first it was missing some modules (like lxml) but I was able to solve it. Now I think I only have problem with docx package.
This is how I initiate the new document in my program (I guess this is what causes me problems):
doc = Document()
#then I do some stuff to it and add paragraph and in the end...
doc.save('results.docx')
When I run it from python everything works fine but when I convert to exe I get this error:
Traceback (most recent call last):
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\cx_Freeze\initscripts\Console.py", line 27, in <module>
exec(code, m.__dict__)
File "tribunalRio.py", line 30, in <module>
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\api.py", line 25, in Document
document_part = Package.open(docx).main_document_part
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\package.py", line 116, in open
pkg_reader = PackageReader.from_file(pkg_file)
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\pkgreader.py", line 32, in from_file
phys_reader = PhysPkgReader(pkg_file)
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\phys_pkg.py", line 31, in __new__
"Package not found at '%s'" % pkg_file
docx.opc.exceptions.PackageNotFoundError: Package not found at 'C:\Users\tyszkap\Dropbox (Dow Jones)\Python Projects\build\exe.win-a
md64-3.4\library.zip\docx\templates\default.docx'
This is my setup.py program:
from cx_Freeze import setup, Executable
executable = Executable( script = "tribunalRio.py" )
# Add certificate to the build
options = {
"build_exe": {'include_files' : ['default.docx'],
'packages' : ["lxml._elementpath", "inspect", "docx", "selenium"]
}
}
setup(
version = "0",
requires = [],
options = options,
executables = [executable])
I thought that explicitly adding default.docx to the package would solve the problem (I have even tried adding it to the library.zip but it gives me even more errors) but it didn't. I have seen this post but I don't know what they mean by:
copying the docx document.py module inside my function (instead of
using Document()
Any ideas? I know that freezing is not the best solution but I really don't want to build a web interface for such a simple program...
EDIT:
I have just tried this solution :
def find_data_file(filename):
if getattr(sys, 'frozen', False):
# The application is frozen
datadir = os.path.dirname(sys.executable)
else:
# The application is not frozen
# Change this bit to match where you store your data files:
datadir = os.path.dirname(__file__)
return os.path.join(datadir, filename)
doc = Document(find_data_file('default.docx'))
but again receive Traceback error (but the file is in this location...):
Traceback (most recent call last):
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\cx_Freeze\initscripts\Console.py", line 27, in <module>
exec(code, m.__dict__)
File "tribunalRio.py", line 43, in <module>
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\api.py", line 25, in Document
document_part = Package.open(docx).main_document_part
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\package.py", line 116, in open
pkg_reader = PackageReader.from_file(pkg_file)
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\pkgreader.py", line 32, in from_file
phys_reader = PhysPkgReader(pkg_file)
File "C:\Users\tyszkap\AppData\Local\Continuum\Anaconda3\lib\site-packages\docx\opc\phys_pkg.py", line 31, in __new__
"Package not found at '%s'" % pkg_file
docx.opc.exceptions.PackageNotFoundError: Package not found at 'C:\Users\tyszkap\Dropbox (Dow Jones)\Python Projects\build\exe.win-a
md64-3.4\default.docx'
What am I doing wrong?
I expect you'll find the problem has to do with your freezing operation not placing the default Document() template in the expected location. It's stored as package data in the python-docx package as docx/templates/default.docx (see setup.py here: https://github.com/python-openxml/python-docx/blob/master/setup.py#L37)
I don't know how to fix that in your case, but that's where the problem is it looks like.
I had the same problem and managed to get around it by doing the following. First, I located the default.docx file in the site-packages. Then, I copied it in the same directory as my .py file. I also start the .docx file with Document() which has a docx=... flag, to which I assigned the value: os.path.join(os.getcwd(), 'default.docx') and now it looks like doc = Document(docx=os.path.join(os.getcwd(), 'default.docx')). The final step was to include the file in the freezing process. Et voilà! So far I have no problem.

Python - Getting error whenever I try to run program "Module cannot be found"

I'm trying to do this little tutorial http://www.roguebasin.com/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod,_part_1
A little ways down the page right before it says moving around it says to test what you have so far. I'm using Pycharm and this is my first time using an outside library or whatever you call it.
This is what I have so far and it is exactly what is in their example:
import libtcodpy as libtcod
#actual size of the window
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50
LIMIT_FPS = 20 #20 frames-per-second maximum
libtcod.console_set_custom_font('terminal.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False)
libtcod.sys_set_fps(LIMIT_FPS)
while not libtcod.console_is_window_closed():
libtcod.console_set_default_foreground(0, libtcod.white)
libtcod.console_put_char(0, 1, 1, '#', libtcod.BKGND_NONE)
libtcod.console_flush()
Whenever I run it I get this error.
Traceback (most recent call last):
File "D:\Programming\Project 1\Rogue Like\libtcodpy.py", line 57, in <module>
_lib = ctypes.cdll['./libtcod-mingw.dll']
File "C:\Python34\lib\ctypes\__init__.py", line 426, in __getitem__
return getattr(self, name)
File "C:\Python34\lib\ctypes\__init__.py", line 421, in __getattr__
dll = self._dlltype(name)
File "C:\Python34\lib\ctypes\__init__.py", line 351, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:/Programming/Project 1/Rogue Like/firstrl.py", line 1, in <module>
import libtcodpy as libtcod
File "D:\Programming\Project 1\Rogue Like\libtcodpy.py", line 60, in <module>
_lib = ctypes.cdll['./libtcod-VS.dll']
File "C:\Python34\lib\ctypes\__init__.py", line 426, in __getitem__
return getattr(self, name)
File "C:\Python34\lib\ctypes\__init__.py", line 421, in __getattr__
dll = self._dlltype(name)
File "C:\Python34\lib\ctypes\__init__.py", line 351, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found
Thanks
I'm assuming you also copied libtcod-VS.dll or libtcod-mingw.dll to the project directory, not just libtcodpy.py. And also SDL.dll and a arial10x10.png. If not, go back and look at the Setting it up instructions again.
But if you have, this isn't really your fault, it's theirs.
libtcodpy.py tries to import the libtcod-VS.dll or libtcod-mingw.dll DLL from the current working directory. You can see that from this line:
_lib = ctypes.cdll['./libtcod-mingw.dll']
So, if the current working directory happens to be anything other than the directory that libtcodpy.py is in, it won't find them there.
This is a silly thing to do. If you do what the Choice of code editor section suggests and always run the script from a console (a "DOS prompt"), it will work (as long as you're always running it without an explicit path), but they really shouldn't be relying on that.
Still, that's obviously the simplest fix: Run the program from the console, the way they're expecting you to, instead of from PyCharm.
Alternatively, you can configure PyCharm to run your project with the project directory as your working directory.
There are a few ways to set this, but the one you probably want is the Run/Debug Configurations dialog (which you can find under Edit Configurations… on the Run menu). Open that dialog, open the disclosure triangle to Defaults, click Python, then look for "Working directory:" on the right. Click the … button and pick your project directory (or wherever you put libtcod-VS.dll or libtcod-mingw.dll).
Or you can edit libtcodpy.py to make it look for the DLL alongside of itself, rather than in the current working directory. There are only 4 small changes you should need.
First, in the middle of the import statements near the top, if there's no import os, add it.
Next, right after the import statements, add this:
modpath = os.path.dirname(os.path.abspath(__FILE__))
Now search for the two lines that start with _lib = ctypes.dll (or just look at the line numbers from the tracebacks) and change them as follows:
_lib = ctyles.cdll(os.path.join(modpath, 'libtcod-mingw.dll'))
_lib = ctyles.cdll(os.path.join(modpath, 'libtcod-VS.dll'))
I've just been struggling with the same problem myself, though I'm using Emacs and Python 2.7.
What solved the problem for me was installing a 32-bit python instead of a 64-bit python. The .dlls in libtcod are 32-bit, and 64-bit python on Windows isn't compatible with 32-bit .dlls.
Also, you might want to check if libtcod is compatible with python 3. I've found two places where the subject is discussed, but I can't tell if libtcod-1.5.1 is compatible with the later 3.xs.
I'd also suggest trying to run the samples_py.py in the libtcod folder to test these two problems, as if that runs it's your folder setup or path, rather then your version of python.

py2exe/pyinstaller and DispatchWithEvents

I have a program that uses the win32com library to control iTunes, but have been having some issues getting it to compile into an executable. The problem seems to revolve around using DispatchWithEvents instead of Dispatch. I've created a very simple program to illustrate my problem:
import win32com.client
win32com.client.gencache.is_readonly = False #From py2exe wiki
class ITunesEvents(object):
def __init__(self): self.comEnabled = True
def OnCOMCallsDisabledEvent(self, reason): self.comEnabled = False
def OnCOMCallsEnabledEvent(self): self.comEnabled = True
# The first line works in the exe, the second doesn't.
itunes = win32com.client.Dispatch("iTunes.Application")
#itunes = win32com.client.DispatchWithEvents("iTunes.Application", ITunesEvents)
lib = getattr(itunes, "LibraryPlaylist")
src = getattr(lib, "Source")
playlists = getattr(src, "Playlists")
print "Found %i playlists." % getattr(playlists, "Count")
Using Dispatch, the program compiles and runs correctly. Using DispatchWithEvents, the program runs fine when called from the command line, but produces the following error when running the exe:
Traceback (most recent call last):
File "sandbox.py", line 16, in <module>
itunes = win32com.client.DispatchWithEvents("iTunes.Application", ITunesEvents)
File "win32com\client\__init__.pyc", line 252, in DispatchWithEvents
File "win32com\client\gencache.pyc", line 520, in EnsureModule
File "win32com\client\gencache.pyc", line 287, in MakeModuleForTypelib
File "win32com\client\makepy.pyc", line 259, in GenerateFromTypeLibSpec
File "win32com\client\gencache.pyc", line 141, in GetGeneratePath
IOError: [Errno 2] No such file or directory: '[distDir]\\library.zip\\win32com\\gen_py\\__init__.py'
I've also tried using PyInstaller, which gives a similar error:
File "<string>", line 16, in <module>
File "[outDir]/win32com.client", line 252, in DispatchWithEvents
File "[outDir]/win32com.client.gencache", line 520, in EnsureModule
File "[outDir]/win32com.client.gencache", line 287, in MakeModuleForTypelib
File "[outDir]/win32com.client.makepy", line 286, in GenerateFromTypeLibSpec
File "[outDir]/win32com.client.gencache", line 550, in AddModuleToCache
File "[outDir]/win32com.client.gencache", line 629, in _GetModule
File "[pyinstallerDir]\iu.py", line 455, in importHook
raise ImportError, "No module named %s" % fqname
ImportError: No module named win32com.gen_py.9E93C96F-CF0D-43F6-8BA8-B807A3370712x0x1x13
I know I can manually add the typelib in my setup.py file, but I'd like to run the code on computers with different versions of iTunes without recompiling so I'd prefer to dynamically create it. If there's no way to do this with the setup/spec, maybe there is another way to load the events? Thanks.
Addition:
Thanks to Ryan, I found I could take the generated py file and after a little digging, was able to come up with the following.
Take the generated py file (from makepy.py) and rename it somewhere like cominterface.py. Then you'll need to do the following to actually create the COM object with event handler.
import cominterface
from types import ClassType
from win32com.client import EventsProxy, _event_setattr_
class ItunesEvents:
'''iTunes events class. See cominterface for details.'''
def OnPlayerPlayEvent(self, t):print "Playing..."
def OnPlayerStopEvent(self, t): print "Stopping..."
itunes = cominterface.iTunesApp()
rClass = ClassType("COMEventClass", (itunes.__class__, itunes.default_source, ItunesEvents), {'__setattr__': _event_setattr_})
instance = rClass(itunes._oleobj_)
itunes.default_source.__init__(instance, instance)
#ItunesEvents.__init__(instance) #Uncomment this line if your events class has __init__.
itunes = EventsProxy(instance)
Then you can go about your business.
I was experiencing the exact same error.
This link put me in the right direction -->
http://www.py2exe.org/index.cgi/UsingEnsureDispatch
however it mentions that :
NB You must ensure that the python...\win32com.client.gen_py dir does not exist
to allow creation of the cache in %temp%
Which was a bit confusing.
What solved it for me was renaming "C:\Python26\Lib\site-packages\win32com\gen_py" to "C:\Python26\Lib\site-packages\win32com\gen_pybak" (when running py2exe)
This is the official way to do it.
(Edit: copied verbatim example from that link above)
import win32com.client
if win32com.client.gencache.is_readonly == True:
#allow gencache to create the cached wrapper objects
win32com.client.gencache.is_readonly = False
# under p2exe the call in gencache to __init__() does not happen
# so we use Rebuild() to force the creation of the gen_py folder
win32com.client.gencache.Rebuild()
# NB You must ensure that the python...\win32com.client.gen_py dir does not exist
# to allow creation of the cache in %temp%
# Use SAPI speech through IDispatch
from win32com.client.gencache import EnsureDispatch
from win32com.client import constants
voice = EnsureDispatch("Sapi.SpVoice", bForDemand=0)
voice.Speak( "Hello World.", constants.SVSFlagsAsync )
Instead of depending on the cache, I'd recommend going into the local cache directory, copying the generated file into your local project file, and naming it something like ITunesInterface.py, and calling to that explicitly. This will make py2exe pull it into your compiled app.

Categories

Resources