Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Python with objc called from within PHP exec not finding Librarys

Python with objc called from within PHP exec not finding Librarys
Thread Tools
Fresh-Faced Recruit
Join Date: Sep 2008
Status: Offline
Reply With Quote
Sep 18, 2008, 02:23 AM
 
edit: should say Libraries, bad spelling sorry!

Hi everyone, First post!

I'm not a python developer at all so some of this may be really dumb!

I have a script that I found from Googling around to take a screenshot of a website and save it as an PNG called screenshot2png.

I've saved it as screenshot2png.sh and chmoded it to be execuatable and it works great, i've even added it to /usr/bin/ so I can call it from anywhere.

But when I try and use the script from exec() in php it doesn't throws the exception below the includes in the try block
and i get

Cannot find pyobjc library files. Are you sure it is installed?

So I'm guessing that I need to include the includes through there full path or some other method?

Any alternative solutions, help or clues would be greatly appreciated!

Below is the script

Code:
//the php print exec("/usr/bin/python screenshot2png.py -D /Applications/MAMP/htdocs/ http://loveis.darwin/"); // results in Cannot find pyobjc library files. Are you sure it is installed?
Code:
//the python #!/usr/bin/python # webkit2png - makes screenshots of webpages # http://www.paranoidfish.org/projects/webkit2png __version__ = "0.4" # $Id: webkit2png-0.4 398 2004-09-24 18:40:49Z paul $ # Copyright (C) 2004 Paul Hammond # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import sys try: import Foundation import WebKit import AppKit import objc except ImportError: print "Cannot find pyobjc library files. Are you sure it is installed?" sys.exit() from optparse import OptionParser class AppDelegate (Foundation.NSObject): # what happens when the app starts up def applicationDidFinishLaunching_(self, aNotification): webview = aNotification.object().windows()[0].contentView() webview.frameLoadDelegate().getURL(webview) class WebkitLoad (Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): # what happens if something goes wrong while loading def webView_didFailLoadWithError_forFrame_(self,webview,error,frame): print " ... something went wrong" self.getURL(webview) def webView_didFailProvisionalLoadWithError_forFrame_(self,webview,error,frame): print " ... something went wrong" self.getURL(webview) def makeFilename(self,URL,options): # make the filename if options.filename: filename = options.filename elif options.md5: try: import md5 except ImportError: print "--md5 requires python md5 library" AppKit.NSApplication.sharedApplication().terminate_(None) filename = md5.new(URL).hexdigest() else: import re filename = re.sub('\W','',URL); filename = re.sub('^http','',filename); if options.datestamp: import time now = time.strftime("%Y%m%d") filename = now + "-" + filename import os dir = os.path.abspath(os.path.expanduser(options.dir)) return os.path.join(dir,filename) def saveImages(self,bitmapdata,filename,options): # save the fullsize png if options.fullsize: bitmapdata.representationUsingType_properties_(AppKit.NSPNGFileType,None).writeToFile_atomically_(filename + "-full.png",objc.YES) if options.thumb or options.clipped: # work out how big the thumbnail is width = bitmapdata.pixelsWide() height = bitmapdata.pixelsHigh() thumbWidth = (width * options.scale) thumbHeight = (height * options.scale) # make the thumbnails in a scratch image scratch = AppKit.NSImage.alloc().initWithSize_( Foundation.NSMakeSize(thumbWidth,thumbHeight)) scratch.lockFocus() AppKit.NSGraphicsContext.currentContext().setImageInterpolation_( AppKit.NSImageInterpolationHigh) thumbRect = Foundation.NSMakeRect(0.0, 0.0, thumbWidth, thumbHeight) clipRect = Foundation.NSMakeRect(0.0, thumbHeight-options.clipheight, options.clipwidth, options.clipheight) bitmapdata.drawInRect_(thumbRect) thumbOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(thumbRect) clipOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(clipRect) scratch.unlockFocus() # save the thumbnails as pngs if options.thumb: thumbOutput.representationUsingType_properties_( AppKit.NSPNGFileType,None ).writeToFile_atomically_(filename + "-thumb.png",objc.YES) if options.clipped: clipOutput.representationUsingType_properties_( AppKit.NSPNGFileType,None ).writeToFile_atomically_(filename + "-clipped.png",objc.YES) def getURL(self,webview): if self.urls: if self.urls[0] == '-': url = sys.stdin.readline().rstrip() if not url: AppKit.NSApplication.sharedApplication().terminate_(None) else: url = self.urls.pop(0) else: AppKit.NSApplication.sharedApplication().terminate_(None) print "Fetching", url, "..." self.resetWebview(webview) webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(Foundation.NSURL.URLWithString_(url))) if not webview.mainFrame().provisionalDataSource(): print " ... not a proper url?" self.getURL(webview) def resetWebview(self,webview): rect = Foundation.NSMakeRect(0,0,self.options.initWidth,self.options.initHeight) webview.window().setContentSize_((self.options.initWidth,self.options.initHeight)) webview.setFrame_(rect) def resizeWebview(self,view): view.window().display() view.window().setContentSize_(view.bounds().size) view.setFrame_(view.bounds()) def captureView(self,view): view.lockFocus() bitmapdata = AppKit.NSBitmapImageRep.alloc() bitmapdata.initWithFocusedViewRect_(view.bounds()) view.unlockFocus() return bitmapdata # what happens when the page has finished loading def webView_didFinishLoadForFrame_(self,webview,frame): # don't care about subframes if (frame == webview.mainFrame()): view = frame.frameView().documentView() self.resizeWebview(view) URL = frame.dataSource().initialRequest().URL().absoluteString() filename = self.makeFilename(URL, self.options) bitmapdata = self.captureView(view) self.saveImages(bitmapdata,filename,self.options) print " ... done" self.getURL(webview) def main(): # parse the command line usage = """%prog [options] [http://example.net/ ...] examples: %prog http://google.com/ # screengrab google %prog -W 1000 -H 1000 http://google.com/ # bigger screengrab of google %prog -T http://google.com/ # just the thumbnail screengrab %prog -TF http://google.com/ # just thumbnail and fullsize grab %prog -o foo http://google.com/ # save images as "foo-thumb.png" etc %prog - # screengrab urls from stdin""" cmdparser = OptionParser(usage, version=("webkit2png "+__version__)) # TODO: add quiet/verbose options cmdparser.add_option("-W", "--width",type="float",default=800.0, help="initial (and minimum) width of browser (default: 800)") cmdparser.add_option("-H", "--height",type="float",default=600.0, help="initial (and minimum) height of browser (default: 600)") cmdparser.add_option("--clipwidth",type="float",default=200.0, help="width of clipped thumbnail (default: 200)", metavar="WIDTH") cmdparser.add_option("--clipheight",type="float",default=150.0, help="height of clipped thumbnail (default: 150)", metavar="HEIGHT") cmdparser.add_option("-s", "--scale",type="float",default=0.25, help="scale factor for thumbnails (default: 0.25)") cmdparser.add_option("-m", "--md5", action="store_true", help="use md5 hash for filename (like del.icio.us)") cmdparser.add_option("-o", "--filename", type="string",default="", metavar="NAME", help="save images as NAME.png,NAME-thumb.png etc") cmdparser.add_option("-F", "--fullsize", action="store_true", help="only create fullsize screenshot") cmdparser.add_option("-T", "--thumb", action="store_true", help="only create thumbnail sreenshot") cmdparser.add_option("-C", "--clipped", action="store_true", help="only create clipped thumbnail screenshot") cmdparser.add_option("-d", "--datestamp", action="store_true", help="include date in filename") cmdparser.add_option("-D", "--dir",type="string",default="./", help="directory to place images into") (options, args) = cmdparser.parse_args() if len(args) == 0: cmdparser.print_help() return if options.filename: if len(args) != 1 or args[0] == "-": print "--filename option requires exactly one url" return if options.scale == 0: cmdparser.error("scale cannot be zero") # make sure we're outputing something if not (options.fullsize or options.thumb or options.clipped): options.fullsize = True options.thumb = True options.clipped = True # work out the initial size of the browser window # (this might need to be larger so clipped image is right size) options.initWidth = (options.clipwidth / options.scale) options.initHeight = (options.clipheight / options.scale) if options.width>options.initWidth: options.initWidth = options.width if options.height>options.initHeight: options.initHeight = options.height app = AppKit.NSApplication.sharedApplication() # create an app delegate delegate = AppDelegate.alloc().init() AppKit.NSApp().setDelegate_(delegate) # create a window rect = Foundation.NSMakeRect(-16000,-16000,100,100) win = AppKit.NSWindow.alloc() win.initWithContentRect_styleMask_backing_defer_ (rect, AppKit.NSBorderlessWindowMask, 2, 0) # create a webview object webview = WebKit.WebView.alloc() webview.initWithFrame_(rect) # turn off scrolling so the content is actually x wide and not x-15 webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) # add the webview to the window win.setContentView_(webview) # create a LoadDelegate loaddelegate = WebkitLoad.alloc().init() loaddelegate.options = options loaddelegate.urls = args webview.setFrameLoadDelegate_(loaddelegate) app.run() if __name__ == '__main__' : main()
(Last edited by robinc; Sep 18, 2008 at 02:26 AM. (Reason:Libraries))
     
Clinically Insane
Join Date: Mar 2001
Location: yes
Status: Offline
Reply With Quote
Sep 18, 2008, 07:52 AM
 
Is invoking your Python script as a cronjob an option? This can be triggered by your PHP script if you'd like.

Otherwise, it looks like you need to add Python's paths to the path of the Apache user. What user does Apache run as? Because this user is generally setup with a non existent shell and home directory, you may have to change the default paths that are visible for all users. This is why I'm thinking that your cronjob route might be better. Not only is it likely easier, but more secure...

Another option might be a SSH tunnel to yourself:

Code:
exec("ssh you@yourserver <python command>")
you'll need to setup SSH keys to be able to automate this workflow without requiring any interaction.
     
robinc  (op)
Fresh-Faced Recruit
Join Date: Sep 2008
Status: Offline
Reply With Quote
Sep 18, 2008, 09:03 AM
 
Hi besson3c , thanks for the reply

Apache2 (in MAMP) runs as robincard which is my user account.

I can't even find a www-user or anything like that.

I wouldn't normally run MAMP, i use a virtualised LAMP in parallels but obviously this python script uses OS X Libraries so I'm running it in MAMP because it's quick and dirty!

If I run

<?
echo exec("whoami");
?>

I get robincard.

Will try the ssh tunnel, a very ingenious solution, hopefully it will work!

Thank you again I'm very grateful for your time.
     
robinc  (op)
Fresh-Faced Recruit
Join Date: Sep 2008
Status: Offline
Reply With Quote
Sep 18, 2008, 09:26 AM
 
also. how do I set up my SSH keys so that I don't have to put in RSA/Passwords etc?
     
Clinically Insane
Join Date: Mar 2001
Location: yes
Status: Offline
Reply With Quote
Sep 18, 2008, 09:31 AM
 
Originally Posted by robinc View Post
Hi besson3c , thanks for the reply

Apache2 (in MAMP) runs as robincard which is my user account.

I can't even find a www-user or anything like that.
Are you running PHP as an Apache module or PHP CGI?

I wouldn't normally run MAMP, i use a virtualised LAMP in parallels but obviously this python script uses OS X Libraries so I'm running it in MAMP because it's quick and dirty!
What OS X libraries does it use?
     
Clinically Insane
Join Date: Mar 2001
Location: yes
Status: Offline
Reply With Quote
Sep 18, 2008, 09:36 AM
 
Originally Posted by robinc View Post
also. how do I set up my SSH keys so that I don't have to put in RSA/Passwords etc?
http://www.networknewz.com/networkne...eyOpenSSH.html

(came up when I googled for "ssh public key")

You may be able to get away with using a password protected key pair since you are running Apache as yourself - ssh-agent should work.
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 07:50 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2