How to open and close a PDF file from within python - python

I can open a PDF file from within Python using subprocess.Popen() but I am having trouble closing the PDF file. How can I close an open PDF file using Python. My code is:
# open the PDF file
plot = subprocess.Popen('open %s' % filename, shell=True)
# user inputs a comment (will subsequently be saved in a file)
comment = raw_input('COMMENT: ')
# close the PDF file
#psutil.Process(plot.pid).get_children()[0].kill()
plot.kill()
Edit: I can close the PDF immediately after opening it (using plot.kill()) but this does not work if there is another command between opening the PDF and 'killing' it. Any help would be great - thanks in advance.

For me, this one works fine (inspired by this). Perhaps, instead of using 'open,' you can use a direct command for the PDF reader? Commands like 'open' tend to make a new process and then shut down immediately. I don't know your environment or anything, but for me, on Linux, this worked:
import subprocess
import signal
import os
filename="test.pdf"
plot = subprocess.Popen("evince '%s'" % filename, stdout=subprocess.PIPE,
shell=True, preexec_fn=os.setsid)
input("test")
os.killpg(os.getpgid(plot.pid), signal.SIGTERM)
On windows/mac, this will probably work if you change 'evince' to the path of the executable of your pdf reader.

Related

Using python to carry out actions in the windows cmd

I have a program, which saves a canvas into a postscript file. The program then opens the file with IrfanView, where I can manually save it as a .png and then I can run another function from python, which does another operation with it and saves it as a .png again. My question is whether there is a way to either cut out the middle manual bit (where I have to click the save as button) or whether the saving from IrfanView can all be done through python code?
This far I've found out that I cannot save the canvas and whatever is on it (im using turtles) can only be saved using postscript.
Also converting postscript to png or jpeg from within python also seems to be a bit of a tall order.
Note: Essentially I use Irfan to do the postscript to .png conversion, but I would like to hide this step of the process from the user, so it would be nice if the program could do it for me.
New Note: I have tried to use the python subprocess module to make a call to the cmd and use that to convert, but whenever I attempt to run the .Popen or the .call function I get an error - Access denied or file not found, either way the commands don't want to run from the python program. I even tried just opening a file from python, through the cmd only to get an error (the same command works when typed directly into the cmd):
WindowsError: [Error 193] %1 is not a valid Win32 application
Assuming that you have a postscript file named saved.ps that you want to convert to a png file with Ghostscript using the device pngalpha, you could do:
gspath = "/path/to/gs" # would be gspath="c:\path\to\gswin32c" on Windows...
infile = "saved.ps"
outfile = "output.png"
gs = subprocess.Popen(["gs", "-o", "output.png", "-sDEVICE=pngalpha",
"-dBatch", infile], executable=gspath,
stdout=subprocess.PIPE, stderr = subprocess.PIPE)
out, err = gs.communicate()
if gs.returncode != 0:
# do error processing, at least display out and err

Getting which file is open in notepad using Python

I want to figure out whether a file is open in Notepad and a File open on Adobe Reader.
If you open task manager, Go to process tab, You can see the "Command Line" column (If not, then Go to View->Select Column) which contains EXE path and opened file's path.
If I get this information, I can easily parse this string to get opened file name (Along with it's path -- Bonus!)
I found an article, which shows the way by PowerShell using WMI. Is there any way to do the same using Python 2.7
I know there's a WMI library for python but not able to figure out how to implement:
Get-CimInstance Win32_Process -Filter "name = 'notepad.exe'" | fl *
I found a way using psutil
import psutil
for pid in psutil.pids():
p = psutil.Process(pid)
if p.name() == "notepad.exe":
print p.cmdline()

How to open a file on mac OSX 10.8.2 in python

I am writing a python code on eclipse and want to open a file that is present in Downloads folder. I am using MAC OSX 10.8.2. I tried with f=os.path.expanduser("~/Downloads/DeletingDocs.txt")
and also with
ss=subprocess.Popen("~/Downloads/DeletingDocs.txt",shell=True)
ss.communicate()
I basically want to open a file in subprocess, to listen to the changes in the opened file.But, the file is not opening in either case.
from os.path import baspath, expanduser
filepath = abspath(expanduser("~/") + '/Downloads/DeletingDocs.txt')
print('Opening file', filepath)
with open(filepath, 'r') as fh:
print(fh.read())
Take note of OSX file-handling tho, the IO is a bit different depending on the filetype.
For instance, a .txt file which under Windows would be considered a "plain text-file" is actually a compressed data-stream under OSX because OSX tries to be "smart" about the storage space.
This can literately ruin your day unless you know about it (been there, had the headache.. moved on)
When double-clicking on a .txt file in OSX for instance normally the text-editor pops up and what it does is call for a os.open() instead of accessing it on a lower level which lets OSX middle layers do disk-area|decompression pipe|file-handle -> Texteditor but if you access the file-object on a lower level you'll end up opening the disk-area where the file is stored and if you print the data you'll get garbage because it's not the data you'd expect.
So try using:
import os
fd = os.open( "foo.txt", os.O_RDONLY )
print(os.read(fd, 1024))
os.close( fd )
And fiddle around with the flags.
I honestly can't remember which of the two opens the file as-is from disk (open() or os.open()) but one of them makes your data look like garbage and sometimes you just get the pointer to the decompression pipe (giving you like 4 bytes of data even tho the text-file is hughe).
If it's tracking/catching updates on a file you want
from time import ctime
from os.path import getmtime, expanduser, abspath
from os import walk
for root, dirs, files in walk(expanduser('~/')):
for fname in files:
modtime = ctime(getmtime(abspath(root + '/' + fname)))
print('File',fname,'was last modified at',modtime)
And if the time differs from your last check, well then do something cool with it.
For instance, you have these libraries for Python to work with:
.csv
.pdf
.odf
.xlsx
And MANY more, so instead of opening an external application as your first fix, try opening them via Python and modify to your liking instead, and only as a last resort (if even then) open external applications via Popen.
But since you requested it (sort of... erm), here's a Popen approach:
from subprocess import Popen, PIPE, STDOUT
from os.path import abspath, expanduser
from time import sleep
run = Popen('open -t ' + abspath(expanduser('~/') + '/example.txt'), shell=True, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
##== Here's an example where you could interact with the process:
##== run.stdin.write('Hey you!\n')
##== run.stdin.flush()
while run.poll() == None:
sleep(1)
Over-explaining your job:
This will print a files contents every time it's changed.
with open('test.txt', 'r') as fh:
import time
while 1:
new_data = fh.read()
if len(new_data) > 0:
fh.seek(0)
print(fh.read())
time.sleep(5)
How it works:
The regular file opener with open() as fh will open up the file and place it as a handle in fh, once you call .read() without any parameters it will fetch the entire contents of the file.
This in turn doesn't close the file, it simply places the "reading" pointer at the back of the file (lets say at position 50 for convenience).
So now your pointer is at character 50 in your file, at the end.
Wherever you write something in your file, that will put more data into it so the next .read() will fetch data from position 50+ making the .read() not empty, so we place the "reading" pointer back to position 0 by issuing .seek(0) and then we print all the data.
Combine that with os.path.getmtime() to fine any reversed changes or 1:1 ratio changes (replacing a character mis-spelling etc).
I am hesitant to answer because this question was double-posted and is confusingly phrased, but... if you want to "open" the file in OSX using the default editor, then add the open command to your subprocess. This works for me:
subprocess.Popen("open myfile.txt",shell=True)
It is most likely a permissions issue, if you try your code in the Python interpreter you will probably receive a "Permission denied" error from the shell when you call subprocess.Popen. If this is the case then you will need to make the file a minimum of 700 (it's probably 644 by default) and you'll probably want 744.
Try the code in the Python interpreter and check for the "Permission denied" error, if you see that then do this in a shell:
chmod 744 ~/Downloads/DeletingDocs.txt
Then run the script. To do it all in Python you can use os.system:
import os
import subprocess
filename = "~/Downloads/DeletingDocs.txt"
os.system("chmod 744 "+filename)
ss=subprocess.Popen(filename, shell=True)
ss.communicate()
The reason it "just works" in Windows is because Windows doesn't support file permission types (read, write and execute) in the same way as *nix systems (e.g. Linux, BSD, OS X, etc.) do.

PDF to PNG in Python with pdf2cairo

I'm looking for a good PDF 2 Image convertor for a long time. I need to convert the PDF to an image in order to print it with use of Qt. I'm programming in Python/Pyside, so if I can convert the PDF to a series of (PNG) images with use of subprocess I can print them without problems.
I achieved to do this by calling convert.exe from Imagemagick. It works quite well but it relies on GhostScript and that is a big package which I want to avoid since its more complex to integrate.
I also tried muPDF from GhostScript, but this seems to not have stdin and stdout options. That's a pity because it first saves my file. Opens it with muPDF, converts and saves it and then reload it again in my Python application. It should be possible without all those steps!
Today I started with experimenting with Poppler's pdf2cairo. I assumed that it would work in this way to convert my (multi paged) PDF to a series of images and pipe it to the stdout. Unfortunately it doesn't and I experience two problems:
It complains that it can only export to stdout when you also use the -singlepage argument. How can I export all pages to stdout?
When I export to stdout I get the error: 'Error opening output file fd://0.png\r\n
Converting a pdf from stdin to image files is no problem it all.
This is my code which also triggers the error about opening the output file:
import subprocess
pdf = open('test.pdf')
p = subprocess.Popen(['pop/pdftocairo.exe', '-singlefile', '-png', '-', '-'],stdin = pdf, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
print(p.stderr.read())
print(p.stdout.read())
I've downloaded PDF2Cairo pre-compiled from: http://blog.alivate.com.au/poppler-windows/
The documentation of the command line options of pdf2cairo can be found here: http://manpages.ubuntu.com/manpages/precise/man1/pdftocairo.1.html
Hopefully you can help me out to make this work!
Update
As you can see below in the answers pdftocairo is buggy and does not work correctly when you want to use stdout. pdftoppm does work it return is byte object of your PDF file:
pdf = open('test.pdf')
p = subprocess.Popen(['pop/pdftoppm.exe', '-png'],stdin = pdf, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
data, error = p.communicate()
The only thing I still need to do is split the byte object into multiple files.
It's a bug in pdftocairo.
The output filename is first passed to getOutputFilename, which returns the special string fd://0 as placeholder for stdout.
But then later that string is passed to getImageFilename which unconditionally adds an extension to the filename, so that later the comparision fails and the program tires to open the literal file fd://0.png instead of using stdout.
Unfortunatlely, the only thing you can do is file a bug report.
As for exporting a multipage document to stdout, that's not supported at all, and it wouldn't work with filetypes like png or jpeg anyway, because these formats don't support multipage documents. It does work for svg, pdf, eps and ps output files, as these formats do support multipage documents (and the processing of the filename done correctly for these.)
I thought it would be easier to just use os.system and pass the whole command string.
This assumes there are "pdfs" and "imgs" folders; change accordingly.
import os
import glob
for pdf_file in glob.glob("pdfs\*.pdf"):
cmd_str = "pdftocairo.exe -jpeg \"%s\" \"%s\"" % (pdf_file, os.path.join("imgs", os.path.splitext(os.path.split(pdf_file)[1])[0]))
print cmd_str
os.system(cmd_str)

save text file and display its content on the browser

If the following script.py writes "some text here" to output.txt file, my URL will be http://my_name/script.py. My question is, how can I read the output.txt as soon as (right after) the following function creates it, so that my URL reads like http://my_name/output.txt.
Many thanks in advance.
#------ script.py -------
def write_txt(){
f=('./output.txt', 'w')
f.write("some text here")
}
try webbrowser lib.
import webbrowser
myurl = "file:///mydir/output.txt"
webbrowser.open(myurl)
However:
Note that on some platforms, trying to
open a filename using this function,
may work and start the operating
system’s associated program.
That is: your file will probably be open in your default text editor (p.e. notepad). A possible solution is to give a custom extension to your file (p.e. output.url) and to associate the extension to your browser (not tested)
Depends on various factors, like OS and webserver used.
Pipe the output to the browser specifying a correct content-type, or, given you script writes to an accessible location, issue a HTTP redirect code pointing to that location.

Categories

Resources