(コマンドラインでの対話式操作とスクリプト)

Description

How to run command-line Python scripts to do batch jobs against Plone sites and Zope application server.

はじめに

Zope provides facilities to run command-line scripts. or maintenance work, like migration script.

  • The output to terminal is instance (Plone buffers HTML output)
  • You can stop processing using CTRL+C
  • You can integrate scripts with standard UNIX tools, like cron

ノート

If the site runs in a single process Zope mode (no ZEO), the actual site instance must be stopped to run a command line script as the one process locks the database (Data.fs).

Command line scripts are also useful for long-running transaction processing

  • A web site runs in multi-client ZEO mode. One client is always offline, reserved for running command-line scripts.
  • Asynchronous long-running transactions are run from this ZEO client, without disturbing the normal site functionality

See also

Starting interactive interpreter

se bin/instance debug command.

Example:

bin/instance debug

Running scripts

Use bin/instance run command.

Example:

bin/instance run src/namespace.mypackage/namespace/mypackage/bin/script.py

Scripting context

The command line interpreter and scripts gets following global context variables

  • app global variable which holds the root of Zope application server.

  • sys.argv contains command-line parameters after python script name

    • argv[0] = script name
    • arvg[1] = first command line argument

To access your site object, you can traverse down from app:

app.yoursiteid # This is your Plone site object

# Perform some stuff here...
for brain in app.yoursiteid.portal_catalog(portal_type="Document"): print brain["Title"]

Committing transactions

You need to manually commit transactions if you change ZODB data from the command line.

Example how to commit:

# Commit transaction
import transaction; transaction.commit()
# Perform ZEO client synchronization (if runnning in clustered mode)
app._p_jar.sync()

More info

zopepy

zopepy buildout recipe creating bin/zopepy command which you can use to run Python scripts in Zope environment set-up (PYTHONPATH, database connection, etc.)

buildout.cfg example:

[zopepy]
# For more information on this step and configuration options see:
#
recipe = zc.recipe.egg
eggs = ${client1:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy

Then running:

bin/zopepy path/to/myscript.py

...or if you want to run a script outside buildout folder:

cd /tmp
/srv/plone/site/bin/zopepy pack2.py

Setting up ZEO for command line-processing

Plone site HTTP requests are processed by one process per requests. One process cannot handle more than one request once. If you need to have long-running transactions you need to at least two front end processes, ZEO clients, so that long-running transactions won’t block your site.

Your code might want to call transaction.commit() now and then to commit the current transaction.

Posing as user

Zope functionality often assumes you have logged in as certain user or you are anonymous user. Command-line scripts do not have user information set by default.

How to set the effective Zope user to admin:

from AccessControl.SecurityManagement import newSecurityManager

# Use Zope application server user database (not plone site)
admin=app.acl_users.getUserById("admin")
newSecurityManager(None, admin)

Spoofing HTTP request

When running from command-line, HTTP request object is not available. Some Zope code might expect this and you need to spoof the request.

Example how to create a dummy request (collective.mountpoint package):

def spoofRequest(self, site):
    """
    Some broken code may the existence of HTTPRequest object via acquisition.

    Note that you can use environment variables given on the command-line to control
    the possible request parameters.

    @param site: Plone site object
    """
    from ZPublisher.HTTPRequest import HTTPRequest

    # Fake HTTP request input
    stdin = StringIO("")

    request = HTTPRequest(stdin=stdin, environ=os.environ, response=FauxResponse())

    site.REQUEST = request

You can set HTTP request parameters in command-line script.

SERVER_NAME=www.mysite.fi
SERVER_PORT=9445
export SERVER_NAME
export SERVER_PORT
bin/client2 run src/collective.mountpoint/collective/mountpoint/bin/update.py mysite

screen

screen is an UNIX command to start a virtual terminal. Screen lets processes run even if your physical terminal becomes disconnected. This effectively allows you to run long-running command line jobs over a crappy Internet connection.

Start new screen

Type command:

screen

If you have sudo’ed to another user you first need to run:

script /dev/null

Attach to an existing screen

Type command:

screen -x