Unable to write to destination pdfkit python - python

Summary
I am trying to use the package pdfkit (version 0.6.1) and wkhtmltopdf (version 0.12.6.0) to convert HTML to PDF.
I can use the script, until I try to convert it to an .exe file using cx_freeze. Then it fails. Using the executable, I get the following error:
Error
Exception in thread Thread-109:
Traceback (most recent call last):
File "C:\Users\Diego\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\Diego\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Diego\Pictures\Zona Python\GuideMath\src\interfaz\VentanaExportar.py", line 132, in __exportarHTMLaPDF
self.__resultado = self.__ctrl.exportarHTMLaPDF(
File "C:\Users\Diego\Pictures\Zona Python\GuideMath\src\controlador\Controlador.py", line 142, in exportarHTMLaPDF
return "E" if pdfkit.from_url(
File "C:\Users\Diego\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pdfkit\api.py", line 26, in from_url
return r.to_pdf(output_path)
File "C:\Users\Diego\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pdfkit\pdfkit.py", line 156, in to_pdf
raise IOError('wkhtmltopdf reported an error:\n' + stderr)
OSError: wkhtmltopdf reported an error:
Loading pages (1/6)
Warning: Javascript alert: Hola
QPainter::begin(): Returned false============================] 100%
Error: Unable to write to destination
Exit with code 1, due to unknown error.
Relevant Code Snippet
pdfConf = pdfkit.configuration(wkhtmltopdf=os.path.join(
self.__principalPath, "docs/web/PDF/wkhtmltopdf.exe"))
pdfOpti = {
"window-status": "print",
"dpi": "90",
# "quiet": "",
"page-size": "A4",
"footer-html": f"{url}/footer.html"
}
try:
return "E" if pdfkit.from_url(
url=f"{url}/document.html",
output_path=outputPath,
configuration=pdfConf,
options=pdfOpti) else "F"
except:
return "F"
Other
I searched on the internet and I found that the problem might be the destination path. But I am using the complete path: C:\Users\Diego\Desktop\JAA.pdf
Setup File
import sys
from cx_Freeze import setup, Executable
build_exe_options = {"packages": ["ctypes", "os", "wx", "json", "threading", "pdfkit"],
"excludes": ["tkinter"]}
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(name="App",
version="0.1",
description="",
options={"build_exe": build_exe_options},
executables=[Executable("main.py", base=base, icon="app.ico")])

The diagnosis you made is correct (after all, Error: Unable to write to destination is pretty straightforward).
If you can create the output file, but the created EXE file cannot - and we know it couldn't - then this means that either
the real destination path is not actually there when the EXE runs. You think you're writing to a given path, but somehow the EXE attempts to write elsewhere.
the EXE has no permissions to create the file.
This might be caused by several reasons. The EXE file, for security reasons, might output in a given directory, so when you ask for "C:\somefile", it actually tries to write in "%TEMP%/C:/somefile". Or might refuse to use a full path.
Or you could need to write the file in Unix syntax ("C:/Users/..." instead of "C:\Users...", because e.g. "\Diego" is translated to "0x0Diego" ("iego" with a carriage return prefixed).
You should therefore insert into the EXE file some code to explore the filesystem the EXE is seeing (which might not be the same one you see!), and/or try to write to a different path, perhaps indeed %TEMP% (where permissions should be sufficient).

Related

os.startfile() not opening .docx file

I am simply trying to open a .docx file, which is stored in the server shared area.
I have tried the following:
notesPath = '//SERVER/shared_data/FolderOne/notes.docx'
os.chdir('//SERVER/shared_data')
os.startfile(notesPath)
With the os.chdir I am changing the path for command prompt, as I believe thats the issue. Becasue when I call os.getcwd() it returns me C:\\Users\\Userone\\Desktop\\. Thats what I though it was good idea to use os.chdir, convert it to //server and go from there.
But when I change the os.chdir in my code, the chdir is set to:
'\\\\SERVER\\shared_data'
with too many slashes
How can I resolve this issue?
Traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Userone\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\Userone\Desktop\project\Main App.py", line 293, in noteopen
os.startfile(notesPath)
FileNotFoundError: [WinError 2] The system cannot find the file specified: '//SERVER/shared_data/FolderOne/notes.docx'
Assuming it's a UNC path, just use a raw string and use back slashes. There should be no need to change the current directory.
notes_path = r'\\SERVER\shared_data\FolderOne\notes.docx'
os.startfile(notes_path)
file_path :- find your application or other file path. put as it is.
file_path = r'C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE'
os.startfile(file_paht)
copy of the application path and pest it.

Subprocess.run() cannot find file, even if path.exists() returns true

I found these two pages:
Subprocess.run() cannot find path
Python3 Subprocess.run cannot find relative referenced file
but it didn't help. The first page talks about using \\ but I already do, and the second one talks about double quotes around one of the arguments.
work = Path("R:\\Work")
resume = work.joinpath("cover_letter_resume_base.doc")
current_date = construct_current_date()
company_name = gather_user_information(question="Company name: ",
error_message="Company name cannot be empty")
position = gather_user_information(question="Position: ",
error_message="Position cannot be empty")
# Construct destination folder string using the company name, job title, and current date
destination = work.joinpath(company_name).joinpath(position).joinpath(current_date)
# Create the destintion folder
os.makedirs(destination, exist_ok=True)
# Construct file name
company_name_position = "{0}_{1}{2}".format(company_name.strip().lower().replace(" ", "_"),
position.strip().lower().replace(" ", "_"), resume.suffix)
resume_with_company_name_job_title = resume.stem.replace("base", company_name_position)
destination_file = destination.joinpath(resume_with_company_name_job_title)
# Copy and rename the resume based on the company and title.
shutil.copy2(src=resume, dst=destination_file)
if destination_file.exists():
print(f"{destination_file} created.")
#subprocess.run(["open", str(destination_file)], check=True)
The program gets the company name and position from the user, generates the current date, creates the directories, and then moves/renames the base resume based on the user input.
Output and Results:
Company name: Microsoft
Position: Software Eng
R:\Work\Microsoft\Software Engineer\20190722\cover_letter_resume_microsoft_software_eng.doc
created.
Error Message:
[WinError 2] The system cannot find the file specified
Traceback (most recent call last):
File "c:/Users/Kiska/python/job-application/main.py", line 59, in <module>
main()
File "c:/Users/Kiska/python/job-application/main.py", line 53, in main
raise error
File "c:/Users/Kiska/python/job-application/main.py", line 48, in main
subprocess.run(["start", str(destination_file)], check=True)
File "C:\Program Files (x86)\Python37-32\lib\subprocess.py", line 472, in run
with Popen(*popenargs, **kwargs) as process:
File "C:\Program Files (x86)\Python37-32\lib\subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "C:\Program Files (x86)\Python37-32\lib\subprocess.py", line 1178, in _execute_child
startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
The if statement returns True but subprocess.run() cannot see the file, but I'm not really sure why.
On which operating system are you? The backslashes in your path suggest that you're on Windows and you're using open to open the document with its default application. However, looking at this question Open document with default OS application in Python, both in Windows and Mac OS you should use start instead of open for Windows:
subprocess.run(["start", str(destination_file)], check=True, shell=True)
Also you need to add shell=True for start to work. However, you should read https://docs.python.org/3/library/subprocess.html#security-considerations beforehand.
(I suspect, the error [WinError 2] The system cannot find the file specified appears, because Windows cannot find open - it's not about the document you're trying to open.)

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.

py2exe is giving errors on my os.listdir code

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

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.

Categories

Resources