ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 02.01.2026

Просмотров: 2723

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

20.6. WRITING A SCRIPT

$ bin/prequest development.ini /

This will print the body of the response to the console on which it was invoked.

Several options are supported by prequest. These should precede any config file name or URL.

prequest has a -d (aka --display-headers) option which prints the status and headers returned by the server before the output:

$ bin/prequest -d development.ini /

This will print the status, then the headers, then the body of the response to the console.

You can add request header values by using the --header option:

$ bin/prequest --header=Host=example.com development.ini /

Headers are added to the WSGI environment by converting them to their CGI/WSGI equivalents (e.g. Host=example.com will insert the HTTP_HOST header variable as the value example.com). Multiple --header options can be supplied. The special header value content-type sets the CONTENT_TYPE in the WSGI environment.

By default, prequest sends a GET request. You can change this by using the -m (aka --method) option. GET, HEAD, POST and DELETE are currently supported. When you use POST, the standard input of the prequest process is used as the POST body:

$ bin/prequest -mPOST development.ini / < somefile

20.6 Writing a Script

All web applications are, at their hearts, systems which accept a request and return a response. When a request is accepted by a Pyramid application, the system receives state from the request which is later relied on by your application code. For example, one view callable may assume it’s working against a request that has a request.matchdict of a particular composition, while another assumes a different composition of the matchdict.

In the meantime, it’s convenient to be able to write a Python script that can work “in a Pyramid environment”, for instance to update database tables used by your Pyramid application. But a “real” Pyramid

219

20. COMMAND-LINE PYRAMID

environment doesn’t have a completely static state independent of a request; your application (and Pyramid itself) is almost always reliant on being able to obtain information from a request. When you run a Python script that simply imports code from your application and tries to run it, there just is no request data, because there isn’t any real web request. Therefore some parts of your application and some Pyramid APIs will not work.

For this reason, Pyramid makes it possible to run a script in an environment much like the environment produced when a particular request reaches your Pyramid application. This is achieved by using the pyramid.paster.bootstrap() command in the body of your script.

latex-note.png

This feature is new as of Pyramid 1.1.

In the simplest case, pyramid.paster.bootstrap() can be used with a single argument, which accepts the PasteDeploy .ini file representing Pyramid your application configuration as a single argument:

from pyramid.paster import bootstrap

env = bootstrap(’/path/to/my/development.ini’) print env[’request’].route_url(’home’)

pyramid.paster.bootstrap() returns a dictionary containing framework-related information. This dictionary will always contain a request object as its request key.

The following keys are available in the env dictionary returned by pyramid.paster.bootstrap():

request

A pyramid.request.Request object implying the current request state for your script.

app

The WSGI application object generated by bootstrapping.

root

220


20.6. WRITING A SCRIPT

The resource root of your Pyramid application. This is an object generated by the root factory configured in your application.

registry

The application registry of your Pyramid application.

closer

A parameterless callable that can be used to pop an internal Pyramid threadlocal stack (used by pyramid.threadlocal.get_current_registry() and pyramid.threadlocal.get_current_request()) when your scripting job is finished.

Let’s assume that the /path/to/my/development.ini file used in the example above looks like so:

[pipeline:main] pipeline = translogger

another

[filter:translogger]

filter_app_factory = egg:Paste#translogger setup_console_handler = False

logger_name = wsgi

[app:another]

use = egg:MyProject

The

configuration

loaded by the above

bootstrap example will use the

configura-

tion

implied by

the [pipeline:main]

section of your configuration file

by default.

Specifying /path/to/my/development.ini is logically equivalent to specifying /path/to/my/development.ini#main. In this case, we’ll be using a configuration that includes an app object which is wrapped in the Paste “translogger” middleware (which logs requests to the console).

You can also specify a particular section of the PasteDeploy .ini file to load instead of main:

from pyramid.paster import bootstrap

env = bootstrap(’/path/to/my/development.ini#another’) print env[’request’].route_url(’home’)

The above example specifies the another app, pipeline, or composite section of your PasteDeploy configuration file. The app object present in the env dictionary returned by pyramid.paster.bootstrap() will be a Pyramid router.

221

20. COMMAND-LINE PYRAMID

20.6.1 Changing the Request

By default, Pyramid will generate a request object in the env dictionary for the URL http://localhost:80/. This means that any URLs generated by Pyramid during the execution of your script will be anchored here. This is generally not what you want.

So how do we make Pyramid generate the correct URLs?

Assuming that you have a route configured in your application like so:

config.add_route(’verify’, ’/verify/{code}’)

You need to inform the Pyramid environment that the WSGI application is handling requests from a certain base. For example, we want to simulate mounting our application at https://example.com/prefix, to ensure that the generated URLs are correct for our deployment. This can be done by either mutating the resulting request object, or more simply by constructing the desired request and passing it into bootstrap():

from pyramid.paster import bootstrap from pyramid.request import Request

request = Request.blank(’/’, base_url=’https://example.com/prefix’)

env = bootstrap(’/path/to/my/development.ini#another’, request=request) print env[’request’].application_url

# will print ’https://example.com/prefix’

Now you can readily use Pyramid’s APIs for generating URLs:

env[’request’].route_url(’verify’, code=’1337’)

# will return ’https://example.com/prefix/verify/1337’

20.6.2 Cleanup

When your scripting logic finishes, it’s good manners to call the closer callback:

from pyramid.paster import bootstrap

env = bootstrap(’/path/to/my/development.ini’)

# .. do stuff ...

env[’closer’]()

222



20.7. MAKING YOUR SCRIPT INTO A CONSOLE SCRIPT

20.6.3 Setting Up Logging

By default, pyramid.paster.bootstrap() does not configure logging parameters present in the configuration file. If you’d like to configure logging based on [logger] and related sections in the configuration file, use the following command:

import logging.config logging.config.fileConfig(’/path/to/my/development.ini’)

20.7 Making Your Script into a Console Script

A “console script” is setuptools terminology for a script that gets installed into the bin directory of a Python virtualenv (or “base” Python environment) when a distribution which houses that script is installed. Because it’s installed into the bin directory of a virtualenv when the distribution is installed, it’s a convenient way to package and distribute functionality that you can call from the command-line. It’s often more convenient to create a console script than it is to create a .py script and instruct people to call it with the “right” Python interpreter. A console script generates a file that lives in bin, and when it’s invoked it will always use the “right” Python environment, which means it will always be invoked in an environment where all the libraries it needs (such as Pyramid) are available.

In general, you can make your script into a console script by doing the following:

Use an existing distribution (such as one you’ve already created via pcreate) or create a new distribution that possesses at least one package or module. It should, within any module within the distribution, house a callable (usually a function) that takes no arguments and which runs any of the code you wish to run.

Add a [console_scripts] section to the entry_points argument of the distribution which creates a mapping between a script name and a dotted name representing the callable you added to your distribution.

Run setup.py develop, setup.py install, or easy_install to get your distribution reinstalled. When you reinstall your distribution, a file representing the script that you named in the last step will be in the bin directory of the virtualenv in which you installed the distribution. It will be executable. Invoking it from a terminal will execute your callable.

As an example, let’s create some code that can be invoked by a console script that prints the deployment settings of a Pyramid application. To do so, we’ll pretend you have a distribution with a package in it named myproject. Within this package, we’ll pretend you’ve added a scripts.py module which contains the following code:

223

20. COMMAND-LINE PYRAMID

1 # myproject.scripts module

2

3 import optparse

4 import sys

5 import textwrap

6

7 from pyramid.paster import bootstrap

8

9 def settings_show():

10description = """\

11Print the deployment settings for a Pyramid application. Example:

12’psettings deployment.ini’

13"""

14usage = "usage: %prog config_uri"

15parser = optparse.OptionParser(

16usage=usage,

17description=textwrap.dedent(description)

18)

19parser.add_option(

20’-o’, ’--omit’,

21dest=’omit’,

22metavar=’PREFIX’,

23type=’string’,

24action=’append’,

25help=("Omit settings which start with PREFIX (you can use this "

26

"option multiple times)")

27

)

28

29options, args = parser.parse_args(sys.argv[1:])

30if not len(args) >= 1:

31print(’You must provide at least one argument’)

32return 2

33config_uri = args[0]

34omit = options.omit

35if omit is None:

36omit = []

37env = bootstrap(config_uri)

38settings, closer = env[’registry’].settings, env[’closer’]

39try:

40for k, v in settings.items():

41

if any([k.startswith(x)

for x

in omit]):

42

continue

 

 

 

43

print(%-40s

%-20s

% (k,

v))

44finally:

45closer()

224


20.7. MAKING YOUR SCRIPT INTO A CONSOLE SCRIPT

This script uses the Python optparse module to allow us to make sense out of extra arguments passed to the script. It uses the pyramid.paster.bootstrap() function to get information about the the application defined by a config file, and prints the deployment settings defined in that config file.

After adding this script to the package, you’ll need to tell your distribution’s setup.py about its existence. Within your distribution’s top-level directory your setup.py file will look something like this:

1

import os

2

 

3

from setuptools import setup, find_packages

4

 

5

here = os.path.abspath(os.path.dirname(__file__))

6

README = open(os.path.join(here, ’README.txt’)).read()

7

CHANGES = open(os.path.join(here, ’CHANGES.txt’)).read()

8

 

9

requires = [’pyramid’, ’pyramid_debugtoolbar’]

10

11setup(name=’MyProject’,

12version=’0.0’,

13description=’My project’,

14long_description=README + \n\n+ CHANGES,

15classifiers=[

16"Programming Language :: Python",

17"Framework :: Pylons",

18"Topic :: Internet :: WWW/HTTP",

19"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",

20],

21author=’’,

22author_email=’’,

23url=’’,

24keywords=’web pyramid pylons’,

25packages=find_packages(),

26include_package_data=True,

27zip_safe=False,

28install_requires=requires,

29tests_require=requires,

30test_suite="myproject",

31entry_points = """\

32[paste.app_factory]

33main = myproject:main

34""",

35)

We’re going to change the

setup.py file to add an

[console_scripts] section with in

the entry_points string.

Within this section,

you should specify a scriptname =

dotted.path.to:yourfunction line. For example:

 

225