Python — network programming

直接在源文件中编写代码

Jython 解释器对于快速检查和作提示都很方便,但您不必在这其中完成所有工作 ― Jython 还允许您在源文件中编写代码,并随后运行该代码(虽然使用 Jython 时,编译步骤是可选的)。以下清单是一个独立 Jython 程序的示例:

清单 7. 模拟硬币投掷的样本 Jython 程序(保存在名为 listing7.py 的文件中)
from java.util import Random
rng = Random()
#This is a comment in Jython
print "Flipping a coin..."
if rng.nextBoolean():
    print "Came up heads"
else:
    print "Came up tails"

在解释如何运行该代码之前,让我们先解释一下代码。这个示例引入了 Jython 中的

语句,这是有些人对 Jython(及其先辈 Python)评论的首要方面之一。没有字符定界符标记出当

语句条件为真时要执行的代码块(Jython 中的条件不需要括起的圆括号,这与 Java 编程一样)。只是这些代码比周围的代码缩进一层。

Jython 代码块总是使用缩进进行标记,而不是使用其它标记,例如花括号。引入代码块的语句(例如

)以冒号作为结尾。Jython 的这个特性意味着在编写代码时必须小心,因为缩进代码的方式实际上可能会改变代码的含义。例如,清单 8a 产生的打印输出只有数字

3,因为它上面两个语句都属于其条件永远不为真的

块:

if 0:
    print "1"
    print "2"
print "3"

如果我只更改其中一行的缩进,那么就会打印数字

2和数字

3:

if 0:
    print "1"
print "2"
print "3"

缩进还必须一致,它必须与将代码组织成块的语句相关联,而且通常它还必须控制代码流。例如:

清单 8c. 缩进:语法错误
print "1"
    print "2"
print "3"

这只会产生一个语法错误,因为没有任何控制语句要求将一个块与代码其余部分相分离。

使用缩进标记代码块是 Python 和 Jython 的更有争议的特性之一,但我认为这个问题常常被夸大了。毕竟,如果您遵循有关缩进的良好的编码标准,就不应该有这种问题。如果遵循了良好的编码缩进,那么机器会执行,同行评论家就无话可说,因此事实胜于雄辩。

此外,我知道当开发人员对这种语言使用一段时间后,没有谁会注意这种限制。适当缩进成为 Jython 的第二本性。缩进和语法之间的这种联系当然可能会引起以前未遇到过的错误,但是没有显式的定界符也消除了使用这些定界符的语言中的某些常见错误。

您可以不必编译就可运行

中的文件(listing7.py),只需将该文件名作为

命令的参数来调用,如下所示:

清单 9. 不编译就运行“硬币投掷”
$ jython listing7.py
Flipping a coin...
Came up tails
$

在上个示例中,

就是 UNIX shell 提示符,它非常象 Windows 系统上的

。您还可以使用

命令将模块编译成 Java 字节码(

)文件,该命令允许您使用

命令直接运行它。用这种方法编译的 Jython 模块有一些限制,但这个问题超出了本文的范围。

Построение глобальных функций

В Jython можно легко создавать глобальные функции, хотя язык Java создание глобальных функций не поддерживает. Также можно определять глобальные переменные (обычно для создания констант без содержащего их класса). К примеру, взгляните на следующий листинг:

START = 1
SPACER = " "

def CounterString(length):
    buffer = ""
    for i in range(START, length):
        buffer = buffer + str(i) + SPACER
    return buffer

print CounterString(10)

Сначала мы определяем две глобальные переменные, которые используются в этой программе в качестве констант — (начало) и (разделитель) — первая является целым числом, а вторая — строкой.

Затем мы определяем функцию с помощью ключевого слова . Эта функция принимает единственный аргумент — целое число с именем (длина). Тот факт, что Jython не контролирует тип аргумента, является преимуществом с точки зрения динамичности языка; но это может стать и недостатком, поскольку некоторые ошибки, связанные с неправильным назначением типов, в отличие от языка Java, могут довольно долго не обнаруживаться.

Заметьте, что строка определения функции заканчивается двоеточием, а это означает начало нового блока, обозначенного отступом последующих строк. Первая строка этого нового блока инициализирует буфер пустой строкой. Этот буфер будет использоваться для хранения результатов работы функции.

Следующая строка создает цикл. Оператор for в Jython принципиально отличается от аналогичного оператора языка Java. В Java вы определяет начальные и конечные условия, а также шаг приращения для каждого цикла. В Jython цикл всегда проходит определенную последовательность от начала и до конца

Обычно эта последовательность имеет вид списка — очень важного типа данных в Jython

Список из трех строковых значений выглядит примерно так:

Если вы хотите перебрать числа от 1 до N (что мы и делаем), вы можете использовать функцию , которая возвращает список чисел в указанном диапазоне. Чтобы лучше ознакомиться с работой этого инструмента, поэкспериментируйте в интерактивной командной строке Jython:

Листинг 11. Примеры функции range()
>>> range(5)

>>> range(1, 5)

>>> range(1, 10, 2)

>>> range(10, 1, -3)

Взгляните на . Каждая итерация цикла исполняет блок кода, дополнительно сдвинутый относительно тела функции. Этот блок состоит из одной строки, в которой текущее содержимое буфера соединяется с новым числом, которое предварительно преобразуется в строку с помощью функции (а не , как было бы в языке Java). Затем к строке добавляется разделитель. После этого цикл прекращается, и возвращается итоговый буфер. Сразу за телом функции следует строка кода для ее проверки. И снова Jython позволяет выполнить это без специальных средств, таких как метод в классе приложения. Результат работы листинга 10 показан ниже:

Getting a Cursor

In order execute any operation, a cursor is required from the
connection. There are two different kinds of cursors: static and dynamic.

The primary difference between the two is the way they manage the
underlying ResultSet. In the static version, the entire ResultSet is
iterated immediately, the data converted and stored with the cursor
and the ResultSet closed. This allows the cursor to know the rowcount
(not available otherwise within JDBC) and set the .rowcount attribute
properly. The major disadvantage to this approach is the space/time
constraints might be extraordinary.

The solution to the problem are dynamic cursors which keep a handle to
the open ResultSet and iterate as required. This drastically decreases
memory consumption and increases perceived response time because no work
is done until asked. The drawback is the .rowcount attribute can never
be accurately set.

To execute a query simply provide the SQL expression and call
execute. The cursor now has a description attribute detailing the column
information. To navigate the result set, call one of the fetch methods
and a list of tuples will be returned.

>>> c = db.cursor()   # this gets a static cursor
 or
>>> c = db.cursor(1)  # this gets a dynamic cursor
>>> c.execute("select count(*) c from player")
>>> c.description

>>> for a in c.fetchall():
...  print a
...
(13569,)
>>>

When finished, close the connections.

>>> c.close()
>>> db.close()
>>>

To call a stored procedure or function provide the name and any params
to callproc. The database engine must support stored procedures. The
examples below have been tested with Oracle, SQLServer and Informix. Refer
to the Python DP API spec for how OUT and INOUT parameters work.

Note

The name of the stored procedure can either be a string or
tuple. This is NOT portable to other DB API implementations.

>>> c = db.cursor() # open the database as in the examples above
>>> c.execute("use northwind")
>>> c.callproc(("northwind", "dbo", "SalesByCategory"), , maxrows=2)
>>> for a in c.description:
...  print a
...
('ProductName', -9, 40, None, None, None, 0)
('TotalPurchase', 3, 17, None, 38, 2, 1)
>>> for a in c.fetchall():
...  print a
...
('Boston Crab Meat', 5318.0)
('Carnarvon Tigers', 8497.0)
>>> c.nextset()
1
>>> print c.fetchall()

>>> print c.description

>>>

2.1.5. Выполнение Python-программ¶

Для выполнения программы, написанной на языке Python, требуется установленный интерпретатор.

В операционных системах Маc или других UNIX-подобных системах Python, как правило, уже установлен. Проверить это можно, введя команду .

В ряде случаев в ОС установлены 2 версии Python — 2.X и 3.X. — тогда команду следует заменять на .

Установка Python рассмотрена отдельно в .

Для запуска интерпретатора Python необходимо набрать в терминале операционной системы (Рисунок 2.1.3).

Рисунок 2.1.3 — Запуск интерпретатора Python

Python предоставляет 2 способа написания программы:

  • интерактивный режим: позволяет организовать диалог между разработчиком/пользователем и терминалом, отображая результат обработки каждой команды (Рисунок 2.1.4);

  • режим запуска файла: выполняет файл с исходным текстом программы целиком (Рисунок 2.1.5).

Рисунок 2.1.4 — Интерактивный режим работы с интерпретатором

Рисунок 2.1.5 — Запуск файла с исходным текстом программы

В дистрибутив Python также входит интегрированная среда разработки IDLE, предоставляющая не только возможность работы, как в интерактивном режиме, так и в качестве текстового редактора, но и ряд других возможностей. На Рисунке 2.1.6 приведен пример работы с IDLE.

Рисунок 2.1.6 — Написание программы в IDLE

Примечание

Какой режим использовать?

Интерактивный режим удобно использовать в случае, если необходимо быстро протестировать небольшой блок кода или даже использовать как калькулятор с большим набором функций. В остальных случаях целесообразнее использовать IDE.

A Simple Client

Let us write a very simple client program which opens a connection to a given port 12345 and given host. This is very simple to create a socket client using Python’s socket module function.

The socket.connect(hosname, port ) opens a TCP connection to hostname on the port. Once you have a socket open, you can read from it like any IO object. When done, remember to close it, as you would close a file.

The following code is a very simple client that connects to a given host and port, reads any available data from the socket, and then exits −

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.

s.connect((host, port))
print s.recv(1024)
s.close()                     # Close the socket when done

Now run this server.py in background and then run above client.py to see the result.

# Following would start a server in background.
$ python server.py & 

# Once server is started run client as follows:
$ python client.py

This would produce following result −

Got connection from ('127.0.0.1', 48437)
Thank you for connecting

No Python C Extension Modules

IronPython scripts can in general import and use regular Python modules.
However, IronPython cannot import C extension modules. Such modules generally
have a .pyd extension, and consist of compiled C or C++, exposing an API to
let them be imported like a Python library.

Such modules include some of the Python standard library, such as cmath, array,
parser, and subprocess. Much of this missing functionality is compensated for
by the availability of equivalent .NET libraries, however this obviously
damages the credibility of IronPython as a plug-in alternative implementation.

Perhaps more significantly for us, this also precludes some commonly-used
3rd-party modules such as NumPy and SciPy. Many of our clients would like
to use these with Resolver One.

构建全局函数

即使 Java 语言不支持全局函数,您也可以用 Jython 轻松创建全局函数。您还可以定义全局变量(通常要设置常量,而不必为它们创建类包装器)。例如,看一下下面的清单:

清单 10. 全局函数以字符串形式返回一系列数字(保存在名为 listing10.py 的文件中)
START = 1
SPACER = " "
def CounterString(length):
    buffer = ""
    for i in range(START, length):
        buffer = buffer + str(i) + SPACER
    return buffer
print CounterString(10)

首先我们定义了两个全局变量

,它们用作该程序的常量,其中一个是整数,而另一个是字符串。

接着我们使用

关键字定义了函数

。该函数有一个称为

的整数参数。Jython 未显式检查该参数是否是整数,这一事实是 Jython 的动态特性的一个优点;但它同时也可能是一个缺点,因为某些类型错误只有在后面的 Java 编程中才能被捕获。

请注意函数特征符行以冒号结尾,从而引入了一个新块,它是通过使后续行缩进来标记的。这一新块的第一行将字符串 buffer 初始化为空字符串。对这个 buffer 进行操作以产生所期望的函数结果。

下一行创建了一个循环。Jython 的

语句与 Java 语言语句完全不同。在 Java 编程中,您可以设置初始和终止条件,以及每个循环步骤。Jython 的循环自始至终总使用一个特殊序列。该序列一般是一个列表,它是 Jython 的一种非常重要的数据类型。

由三个字符串组成的列表如下所示:

如果您想对从

1到

N 的数字作循环(如同我们这里所做的),那么可以使用函数

,它返回给定范围内的数字列表。在交互式 Jython 提示符下做些实验应该会帮助您熟悉这个工具:

清单 11. range() 函数示例
>>> range(5)

>>> range(1, 5)

>>> range(1, 10, 2)

>>> range(10, 1, -3)

回过头看一下

循环的每个迭代都作为一个代码块运行,该代码块从该函数体其余部分缩进一层。该块是将当前 buffer 并置到新数字的一行代码,首先使用

函数(而不是 Java 编程中的

)将新数字强制转换成字符串,随后追加一个分隔符。该循环终止后,返回最终的 buffer。该函数体之后的一行代码对它进行测试。Jython 同样允许您不使用任何特殊工具(如应用程序类上的

方法)就可以完成这个任务。清单 10 的输出显示如下:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector