суббота, 10 августа 2013 г.

Спецификаторы формата для целых чисел Python

Спецификаторы формата для целых чисел.

Начинаются с символа двоеточия (:)

Далее следует пара необязательных символов:

- символ заполнителя (который не может быть правой фигурной скобкой   } )

- символ выравнивания:

"<"  - по левому краю
"^"  - по центру
">"  - по правому краю
"="  - указывающий на необходимость заполнять пространство между знаком числа и первой значащей цифрой.

Далее следует необязательный символ знака числа:

"+"  - говорит об обязательной необходимости вывода знака числа

"-"  - знак выводится только для отрицательных чисел

" "  - для положительных чисел вместо знака выводить пробел, для отрицательных чисел знак "-"

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


Рассмотрим некоторые примеры:

print("{0:0=12}".format(8749203))
print("{0:0=12}".format(-8749203))

print("{0:012}".format(8749203))
print("{0:012}".format(-8749203))

> 000008749203
   -00008749203
   000008749203
   -00008749203

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

Во вторых двух примерах определяется минимальная ширина поля вывода 12 символов и признак необходимости дополнения нулями.


Управление выравниванием:

print("{0:*<15}".format(18340427))

> 18340427*******



print("{0:*>15}".format(18340427))

> *******18340427


print("{0:*^15}".format(18340427))

> ***18340427****


print("{0:*^15}".format(-18340427))

> ***-18340427***


Управление выводом знака числа:

пробел или знак "-"

print("[{0: }][{1: }]".format(539802, -539802))

> [ 539802][-539802]



знак выводится принудительно

print("[{0:+}][{1:+}]".format(539802, -539802))

> [+539802][-539802]


знак "-" выводится только принеобходимости

print("[{0:-}][{1:-}]".format(539802, -539802))

> [539802][-539802]



Если число должно выводиться в системе исчисления, отличной от десятичной,
необходимо указать символ типа системы исчисления.

b  - для двоичной

o  - для восьмеричной

x  - для шестнадцатеричной с символами в нижнем регистре

X  - для шестнацатеричной с символами в верхнем регистре

d  - для десятичной


Использование символов управления типом:

print("{0:b}   {0:o}   {0:x}   {0:X}   {0:d}".format(14613198))

> 110111101111101011001110   67575316   deface   DEFACE   14613198


если перед символом типа поставить символ "#"
то вывод будет выглядеть с указанием системы исчисления:

print("{0:#b}   {0:#o}   {0:#x}   {0:#X}   {0:#d}".format(14613198))

> 0b110111101111101011001110   0o67575316   0xdeface   0XDEFACE   14613198



Существует еще один символ типа:

c  - означает что должен выводиться символ unicode соответствующий целому числу.

print("{0:#c}".format(1288))

> Ԉ



И последний символ управления форматом вывода:

n  - когда реобходимо обеспечить вывод чисел с учетом региональных настроек.

он доступен также для чисел с плавающей точкой

Он имеет то же действие что и d в случае целых чисел
или g в случае вывода чиселс плавающей точкой.

Отличительной особенностью символа n является то, что он учитывает региональные настройки,
т.е. использует характерный для текущего региона символ-разделитель целой и дробной части числа
и разделитель разрядов.

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

Чтобы иметь возможность принимать во внимание региональные настройки пользователя,
в начале программы в качестве двух первых выполняемых инструкций можно добавить следующие две строки:


import locale
locale.setlocale(locale.LC_ALL, "")

 Передавая пустую строку в качестве названия региона, мы тем самым предлагаем интерпретатору
попытаться автоматически определить регион пользователя, путем определения переменной окружения LANG.

import locale
locale.setlocale(locale.LC_ALL, "")

x, y = (1234567890, 1234.56)
print("{0:n}    {1:n}".format(x,y))

> 1 234 567 890    1 234,56



import locale
locale.setlocale(locale.LC_ALL, "C")

x, y = (1234567890, 1234.56)
print("{0:n}    {1:n}".format(x,y))

> 1234567890    1234.56



import locale
locale.setlocale(locale.LC_ALL, "en_US.UTF-8")

x, y = (1234567890, 1234.56)
print("{0:n}    {1:n}".format(x,y))

> 1,234,567,890    1,234.56



import locale
locale.setlocale(locale.LC_ALL, "de_DE.UTF-8")

x, y = (1234567890, 1234.56)
print("{0:n}    {1:n}".format(x,y))

> 1.234.567.890    1.234,56


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



Форматирование строк в Python

Метод   str.format()   возвращает новую строку, замещая поля в контекстной строке соответствующими аргументами.

 "строка".format()

print("строка".format())

> строка

 print("abc".format())

> abc


Функция format() может принимать аргументы:

- строки
- числа
- другие коллекции


.format("строка",  число,  имя_коллекции)

И все эти аргументы могут подставляться в любое место исходной строки.

"строка     ....    .....    ......    ....   abc".format(arg1, arg2, arg3)


Примеры:

print("   {0}   {1}   {2}   ".format("abc", 13, 8))

>   abc   13   8


print("   {1}   {2}   {0}   ".format("abc", 13, 8))

 >  13   8   abc



print("xxx   {0}   xxx".format("abcd"))

> xxx   abcd   xxx


xx   {0[0]}   xxx".format("abcd"))

> xxx   a   xxx


print("xxx   {0[0]}  {0[3]}   xxx".format("abcd"))

> xxx   a  d   xxx


print("Цвет: {0}\nРазмер: {1}".format("зеленый", 44))

> Цвет: зеленый
   Размер: 44


print("{1}{0}".format(500, "Цена $"))

> Цена $500


Если попытаться объединить строку и число, интерпретатор Python совершенно справедливо возбудит исключение TypeError.

Но это легко сделать с помощью метода str.format()

print("{0}{1}".format("The amount due is  $", 500))

> The amount due is  $500



Если нам потребуется включить фигурные скобки в строку формата, то это можно сделать дублируя их:

print("{{ {0} }},  {1}: }}".format("Эта строка в фигурных скобках", "а это просто фигурная скобка"))

> { Эта строка в фигурных скобках },  а это просто фигурная скобка: }


С помощью str.format()  мы также легко можем объединять строки.
(хотя для этой цели лучше подойдет метод str.join() )

x = "three"
s = "{0} {1} {2}"
s = s.format("The", x, "tops")
print(s)

> The three tops


Во всех примерах, где использовались строковые литералы, точно так же можно было бы использовать и строковые переменные.

Замещаемые поля могут определяться одним из следующих способов:

{field_name}

{field_name!conversion}

{field_name:format_specification}

{field_name!conversion:format_specification}


Следует заметить, что замещаемые поля могут содержать другие замещаемые поля.
Вложенные замещаемые поля не могут иметь какое-либо форматирование - их назначение состоит в том, чтобы позволить динамически определять параметры форматирования.


Имена полей


Имя поля может быть либо целым числом, соответствующим одному из аргументов метода str.format() либо именем одного из именованных аргументов метода.

Кроме позиционных аргументов можно использовать именованные аргументы:

" {имя_1} {имя_2} ".format(имя_1 = "строка",  имя_2 = число)



print("Цвет: {цвет} Размер: {размер}".format(цвет = "зеленый", размер = 44))

> Цвет: зеленый  Размер: 44


print("Цвет: {цвет}  Размер: {0}".format(44, цвет = "зеленый"))

> Цвет: зеленый  Размер: 44


В первом примере используется два именованных аргумента: цвет и размер.
Во втором примере используется один позиционный аргумент и один именованный аргумент.

Обратите внимание, что в списке аргументов именованные аргументы всегда следуют после позиционных.

В строке формата мы можем использовать любые аргументы в любом порядке.


Позиционные и именованные аргументы

Используем индекс позиционного элемента или имя именованного аргумента
{0} или размер, цвет


print("Размер {0}".format(44))
print("Размер {размер}".format(размер = 44))

> Размер 44
   Размер 44

print("Цвет {0}".format("зеленый"))
print("Цвет {цвет}".format(цвет = "зеленый"))

> Цвет зеленый
   Цвет зеленый



Если это список

Используем индекс позиционного элемента или имя именованного аргумента
{0} или n - имя списка

цвет = ["красный", "синий", "зеленый"]
print("{0[1]}".format(цвет))
print("{n[2]}".format(n = цвет))

> синий
   зеленый

Если это словарь

Используем индекс позиционного элемента или имя именованного аргумента
{0} или n - имя словаря

d = dict(цвет = "зеленый", размер = 44)
print("{0[цвет]}".format(d))
print("{n[размер]}".format(n = d))

> зеленый
   44


Если это объект

Используем индекс позиционного элемента или имя именованного аргумента
{0} или n - имя объекта

import math
print("{0.pi}".format(math))
print("{m.pi}".format(m = math))

> 3.141592653589793
   3.141592653589793


Различные типы данных в Python могут одним из двух способов:

Первый способ отображения - это репрезентативная форма.
Ее назначение состоит в том, чтобы предоставить строку, которая может быть воспринята интерпретатором Python для воссоздания объекта, который она представляет.

Второй способ отображения - это строковая форма.
Эта форма предназначена для представления человеку, поэтому основное ее предназначение состоит в том, чтобы отображать информацию в том виде, в котором она будет иметь определенный смысл для человека.

Не все объекты могут быть представлены в форме, позволяющей выполнить их воспроизведение, в таких случаях они представляются в виде строки, заключенной в угловые скобки:

Например репрезентативной формой модуля sys является строка:

>>> import sys
>>> sys

>>> print(sys)

>>>



Функция  print()  пытается отобразить объект в строковой форме, если тип данных не имеет строковой формы представления объект будет отображен в репрезентативной форме.

Метод str.format()  по умолчанию также использует строковую форму, но с помощью спецификаторов можно изменить форму вывода объекта.

Метод str.format() поддерживает три спецификатора преобразования:

s - для принудительного вывода строковой формы

r - для принудительного вывода репрезентативной формы

a - для принудительного вывода репрезентативной формы, но с использованием только символов  ASCII.


import decimal
print("{0}  {0!s}  {0!r}  {0!a}".format(decimal.Decimal("3.1415")))

> 3.1415  3.1415  Decimal('3.1415')  Decimal('3.1415')


 Пример с unicode:

s = 'AÜBÖC'
print("{0}".format(s))
print("{0!a}".format(s))
print(ascii(s))

> AÜBÖC
  'A\xdcB\xd6C'
  'A\xdcB\xd6C'


Спецификаторы формата строк.

Начинаются с символа двоеточия (:)

Далее следует пара необязательных символов:

- символ заполнителя (который не может быть правой фигурной скобкой   } )

- символ выравнивания:

"<"  - по левому краю
"^"  - по центру
">"  - по правому краю


Если указан символ-заполнитель, то должно быть и направление выравнивания.

Вполне безопасно (хотя и бессмысленно) использовать одно только двоеточие без указания дополнительных элементов спецификатора.

Далее следует необязательное число, определяющее минимальную ширину поля вывода.
И далее при желании, через точку можно указывать максимальную ширину поля вывода.


s = "Строка символов"
print("{0}".format(s))

> Строка символов


s = "Строка символов"
print("{0:}".format(s))

> Строка символов


Если символ-заполнитель и символ выравнивания не указаны, то по умолчанию строка будет выравнена по левому краю и в конце дополнена пробелами до указанной минимальной ширины поля:

s = "Строка символов"
print("{0:25}".format(s))

> Строка символов


Символ заполнителя без символа выравнивания использовать нельзя:
s = "Строка символов"
print("{0:#25}".format(s))

> Traceback (most recent call last):
  File "None", line 2, in
builtins.ValueError: Alternate form (#) not allowed in string format specifier



s = "Строка символов"
print("{0:#<25}".format(s))

> Строка символов##########


А символ выравнивания можно использовать без символа заполнителя:

s = "Строка символов"
print("{0:>25}".format(s))

>          Строка символов


Еще примеры:

s = "Строка символов"
print("{0:^25}".format(s))

>      Строка символов


s = "Строка символов"
print("{0:-^25}".format(s))

> -----Строка символов-----


В следующем примере необходимо определить выравнивание по левому краю (даже при том, что это значение по умолчанию)
В противном случае спецификатор формата приобрел бы вид :.25
а это просто означает максимальную ширину поля вывода 25 символов.

s = "Строка символов"
print("{0:.<25}".format(s))

> Строка символов..........


Если максимальная ширина поля вывода не достаточна для вывода всей строки, то строка будет усечена.

s = "Строка символов"
print("{0:.10}".format(s))

> Строка сим


Как уже отмечалось ранее, внутри спецификатора формата можно использовать замещаемые поля.
Это делает возможным динамически определять формат вывода.

Два способа определить максимальную ширину строки с помощью переменной maxwidth:

s = "Строка символов"
maxwidth = 12
print("{0}".format(s[:maxwidth]))

> Строка симво


s = "Строка символов"
maxwidth = 12
print("{0:.{1}}".format(s, maxwidth))

 > Строка симво


В первом случае используется обычная операция извлечения среза.

Во втором - вложенное замещаемое поле.




понедельник, 5 августа 2013 г.

Основы JavaScript

Любой HTML или XHTML - документ состоит из четырех разделов:

<!DOCTYPE>
контейнера <html>
заголовка <head>
тела документа <body>


Любой HTML-документ начинается со строки, содержащей декларацию типа документа (DTD, document type declaration).
HTML 4.0 поддерживает три типа таких деклараций:


Документ строго соответствует стандарту HTML 4.0, т. е. не содержит ни морально устаревших элементов, ни фреймов:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">


Документ является переходным к стандарту HTML 4.0, т. е. может содержать морально устаревшие элементы:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">


Документ содержит фреймы:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN"
 "http://www.w3.org/TR/html4/frameset.dtd">




Любой XHTML-документ также начинается со строки, содержащей декларацию типа документа:

XHTML 1.0 Strict
Используется в том случае, если в документе идет четкое разделение оформления и содержания.
При этом код веб-страницы содержит только теги разметки, а сам вид элементов задается через стили:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


XHTML 1.0 Transitional
Обычно применяется, когда правило разделения оформления и содержания выполняется не в полной мере.
В этом случае допускается в коде документа использовать теги физического проектирования
и лишь частично стили.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


XHTML 1.0 Frameset
Применяется, когда окно браузера делится на два или более фрейма:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">



Простейший HTML-документ

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <!-- Заголовка страницы -->
  </head> 
  <body>
   <!-- Содержимое страницы -->
  </body>
</html>


Сценарии JavaScript можно вставлять между тегами:

<head></head>

или

<body></body>

Простейший пример сценария:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title> Заголовок документа </title>
  </head> 
  <body>
    Пример сценария
    <br />
    <script type="text/javascript">
      document.write("Hello World!");
    </script>
    <br />
    Простой вывод текста
  </body>
</html>



Можно текст сценария помесить во внешний файл, например jsfile1.js
Этот файл содержит следующее:

document.write("Hello World!");

а затем  вызвать его из html - документа:

<script type="text/javascript" src="jsfile1.js">
</script>


Предыдущий пример изменится так:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title> Заголовок документа </title>
  </head>
  <body>
    Пример сценария
    <br />
    <script type="text/javascript" src="jsfile1.js">
    </script>
    <br />
    Простой вывод текста
  </body>
</html>



На самом деле все сценарии лучше выносить во внешние файлы.

Например усли поместить в html - документ сценарий javascript,
который содержит символы сравнения (меньше чем)  x < y то будут проблемы
и страница не пройдет проверку т.к. символ  <  выглядит как начало нового тега.

Чтобы этого избежать нужно использовать раздел CDATA и закомментарить его:

<script type="text/javascript">

/*<![CDATA[*/

var x=5;
var y=10;
if (x < y) {
window.alert("x меньше, чем y");
}

/*]]>*/


</script>


т.е. раздел CDATA нужен, чтобы страница прошла проверку
а комментарии нужны, чтобы сценарий запускался.

Теперь наш пример будет выглядеть так:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title> Заголовок документа </title>
  </head>
  <body>
    Пример сценария
    <br />
    <script type="text/javascript">
    /*<![CDATA[*/
    var x=5;
    var y=10;
    if (x < y) {
    window.alert("x меньше, чем y");
    }
    /*]]>*/
    </script>
    <br />
    Использование сценария внутри html - документа
  </body>
</html>




Для html 4.01 тип документа описывался так:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
 "http://www.w3.org/TR/html4/strict.dtd">


В html 5 все намного проще:

<!doctype html>
<html>
  <head>
  <meta charset="UTF-8">
  <title> Заголовок документа </title>
    <script>
    alert("Hello World!")
    </script>
  </head>
  <body>
  <!-- Содержимое страницы -->
  </body>
</html>


Пример html - документа, который содержит внешний скрипт, внутренний скрипт и таблицу стилей:

<!doctype html>
<html>
  <head>
  <meta charset="UTF-8">
  <title> Заголовок документа </title>

    <link href="../_css/title.css" rel="stylesheet">

    <script src="../_js/jquery-1.6.3.min.js">
    </script>

    <script>
    $(document).ready(function() {
    $('body').hide().fadeIn(3000);
    });
    </script>

  </head>
  <body>
  <!-- Содержимое страницы -->
  </body>
</html>



суббота, 27 июля 2013 г.

Работа с файлами в Python

Вывод в файлы:

file = open('data.txt', 'w')

Если полный путь к файлу не указан, то файл будет создан в текущем рабочем каталоге.
Если в этом каталоге уже существует такой файл, то он будет удален и создан новый.
С режимом "w" нужно быть осторожнее, можно потерять содержимое старого файла.


myfile = open("C:\\projects\\data.txt", "w")
myfile.write("# Name Email Phone\n")
myfile.write("Larry larry@example.com 111-1111\n")
myfile.write("Curly curly@example.com 222-2222\n")
myfile.write("Moe moe@example.com 333-3333\n")
myfile.close()


c:\projects>type data.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

c:\projects>

В отличии от функции print, метод write объекта файла записывает в точности то,
что ему передано, без дополнительного форматирования.
Поэтому мы явно добавляем символ конца строки.

Метод close завершает формирование содержимого файла и освобождает системные ресурсы.
Обычно файлы автоматически закрываются, когда объект файла уничтожается
интерпретатором при сборке мусора (т.е. когда в сценарии исчезнет послдняя ссылка на объект)

В случае использования временных файлов, метод close можно и не применять:

open('tempfile.txt','w').write("Scott Tiger\n")
open('tempfile.txt','r').read()


Гарантированное закрытие файлов:

- Использовать обработчик исключений

myfile = open("C:\\projects\\data.txt", "w")
try:
    myfile.write("# Name Email Phone\n")
    myfile.write("Larry larry@example.com 111-1111\n")
    myfile.write("Curly curly@example.com 222-2222\n")
    myfile.write("Moe moe@example.com 333-3333\n")
finally:
    myfile.close()


c:\projects>type data.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

- использовать менеджер контекста

Инструкция with - обеспечивает  более краткий способ реализации заключительных
операций для объектов определенных типов, включая закрытие файлов.

with open("C:\\projects\\data.txt", "w")  as myfile:
    # обработка файла
    myfile.write("# Name Email Phone\n")
    myfile.write("Larry larry@example.com 111-1111\n")
    myfile.write("Curly curly@example.com 222-2222\n")
    myfile.write("Moe moe@example.com 333-3333\n")
    # закрывается автоматически после выхода
    # независимо от возникновения исключений

c:\projects>type data.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

В версии Python 3.1 появились вложенные менеджеры контекста:

with A() as a, B() as b:
    # инструкции

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

Это действует так:
with A() as a:
    with B() as b:
        # инструкции


Например:

with open("C:\\projects\\data.txt") as fin, open("C:\\projects\\data1.txt", 'w') as fout:
    for line in fin:
        fout.write(line.upper())

C:\Users\angor>cd c:\projects

c:\projects>type data.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

c:\projects>type data1.txt
# NAME EMAIL PHONE
LARRY LARRY@EXAMPLE.COM 111-1111
CURLY CURLY@EXAMPLE.COM 222-2222
MOE MOE@EXAMPLE.COM 333-3333

c:\projects>

Для записи в файлы можно также использовать метод writelines,
который просто записывает все строки из списка без дополнительного форматирования.

myfile = open("C:\\projects\\data.txt", "w")
myfile.writelines(["# Name Email Phone\n",
                  "Larry larry@example.com 111-1111\n",
                  "Curly curly@example.com 222-2222\n",
                  "Moe moe@example.com 333-3333\n"])
myfile.close()

C:\Users\angor>cd c:\projects

c:\projects>type data.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

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


Чтение из файлов:

file = open('data.txt', 'r')

режим r используется по умолчанию, поэтому можем писать так:

file = open('data.txt')


пример:

myfile = open("C:\\projects\\data.txt")
lines = myfile.readlines()
for line in lines:
    print(line, end='')


# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Метод readlines загружает содержимое файла в память целиком
и передает его сценарию в виде списка строк, который можно обойти в цикле.

Существует много способов чтения вхлдного файла:

file.read()
возвращает строку, содержащую все символы (или байты), хранящиеся в файле.


file.read(N)
возвращает строку, содержащую очередные N символов (или байтов), из файла.


file.readline()
читает содержимое файла до ближайшего символа \n и возвращает строку.


file.readlines()
читает файл целиком и возвращает список строк


Вызов метода seek(0) перед каждой попыткой чтения переустанавливает текущую позицию чтения в начало файла.

Python 3.3.1 (v3.3.1:d9893d13c628, Apr  6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> myfile = open("C:\\projects\\data.txt")
>>> myfile.seek(0)
0
>>> myfile.read()
'# Name Email Phone\nLarry larry@example.com 111-1111\nCurly curly@example.com 222-2222\nMoe moe@example.com 333-3333\n'


>>> myfile.seek(0)
0
>>> myfile.readlines()
['# Name Email Phone\n', 'Larry larry@example.com 111-1111\n', 'Curly curly@example.com 222-2222\n', 'Moe moe@example.com 333-3333\n']


>>> myfile.seek(0)
0
>>> myfile.readline()
'# Name Email Phone\n'

>>> myfile.readline()
'Larry larry@example.com 111-1111\n'

>>> myfile.readline()
'Curly curly@example.com 222-2222\n'

>>> myfile.readline()
'Moe moe@example.com 333-3333\n'

>>> myfile.readline()
''

>>> myfile.readline()
''


>>> myfile.seek(0)
0
>>> myfile.read(1)
'#'
>>>
>>> myfile.read(8)
' Name Em'



>>> myfile.seek(0)
0
>>> myfile.read(1), myfile.read(8)
('#', ' Name Em')
>>>



Методы read() и readlines() загружают в память сразу весь файл.
Их можно использовать при работе с небольшими файлами.

Для работы с потенциально большими файлами необходимо использовать вызовы

readline() и read(N)

Оба метода возвращают пустую строку по достижении конца файла.

seek(0) - означает вернуться в начало файла
это альтернатива повторному открытию файла перед очередной попыткой чтения из него.


Чтение строк с помощью итераторов файлов

В старых версиях Python принято было читать файл в список и одход этого списка в цикле:

myfile = open("C:\\projects\\data.txt")
for line in myfile.readlines():
    print(line, end='')

# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333

Больше не делайте так никогда !!!

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

Теперь нет необходимости вызывать метод readlines.

myfile = open("C:\\projects\\data.txt")
for line in myfile:
    print(line, end='')


# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Более того теперь файл можно открывать непосредственно в инструкции цикла,
как временный, который будет автоматически закрыт после выхода из цикла:

for line in open("C:\\projects\\data.txt"):
    print(line, end='')


# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Это наиболее предпочтительный способ чтения из файла на сегодняшний день.


Вообще итератор это всего лишь метод

__next__ , вызываемый встроенной функцией next.

Он своим поведением напоминает метод readline, за исключением того ,
что по достижении конца файла методы чтения возвращают пустую строку,
а итератор возбуждает исключение, чтобы прервать итерации.

Python 3.3.1 (v3.3.1:d9893d13c628, Apr  6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> myfile = open("C:\\projects\\data.txt")
>>> myfile.readline()
'# Name Email Phone\n'
>>> myfile.readline()
'Larry larry@example.com 111-1111\n'
>>> myfile.readline()
'Curly curly@example.com 222-2222\n'
>>> myfile.readline()
'Moe moe@example.com 333-3333\n'
>>> myfile.readline()
''
>>>
>>>
>>>
>>> myfile = open("C:\\projects\\data.txt")
>>> myfile.__next__()
'# Name Email Phone\n'
>>> myfile.__next__()
'Larry larry@example.com 111-1111\n'
>>> myfile.__next__()
'Curly curly@example.com 222-2222\n'
>>> myfile.__next__()
'Moe moe@example.com 333-3333\n'
>>> myfile.__next__()
Traceback (most recent call last):
  File "", line 1, in
    myfile.__next__()
StopIteration
>>>


Интересно отметить, что итераторы автоматически используются во всех итерационных контекстах,
включая конструктор списка, генераторы списков, функцию map и оператор in проверки на вхождение:

>>> open("C:\\projects\\data.txt").readlines()
['# Name Email Phone\n', 'Larry larry@example.com 111-1111\n', 'Curly curly@example.com 222-2222\n', 'Moe moe@example.com 333-3333\n']
>>>
 

>>> list(open("C:\\projects\\data.txt"))
['# Name Email Phone\n', 'Larry larry@example.com 111-1111\n', 'Curly curly@example.com 222-2222\n', 'Moe moe@example.com 333-3333\n']
>>>

>>> lines=[line.rstrip() for line in open("C:\\projects\\data.txt")]
>>> lines
['# Name Email Phone', 'Larry larry@example.com 111-1111', 'Curly curly@example.com 222-2222', 'Moe moe@example.com 333-3333']
>>>

>>> lines=[line.upper() for line in open("C:\\projects\\data.txt")]
>>> lines
['# NAME EMAIL PHONE\n', 'LARRY LARRY@EXAMPLE.COM 111-1111\n', 'CURLY CURLY@EXAMPLE.COM 222-2222\n', 'MOE MOE@EXAMPLE.COM 333-3333\n']
>>>

>>> list(map(str.split, open("C:\\projects\\data.txt")))
[['#', 'Name', 'Email', 'Phone'], ['Larry', 'larry@example.com', '111-1111'], ['Curly', 'curly@example.com', '222-2222'], ['Moe', 'moe@example.com', '333-3333']]
>>>

>>> line = '# Name Email Phone\n'
>>> line in open("C:\\projects\\data.txt")
True
>>>


Примеры:

Чтение строк из файла и вывод их с помощью функции print:


f = open("C:\\projects\\data.txt", "r")
while True:
    theline = f.readline()
    if len(theline) == 0:
        break
    print(theline, end="")
f.close()

# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Чтение строк из файла, сортировка их в памяти и запись в другой файл:

fin = open("C:\\projects\\data.txt", "r")
buf = fin.readlines()
fin.close()
buf.sort()
fout = open("C:\\projects\\data1.txt", "w")
for line in buf:
    fout.write(line)
    print(line)
fout.close()

# Name Email Phone
Curly curly@example.com 222-2222
Larry larry@example.com 111-1111
Moe moe@example.com 333-3333

Чтение строк из файла, создание списка слов из этого файла, и вывод количества слов:

f = open("C:\\projects\\data.txt")
content = f.read()
f.close()
words = content.split()
print(words)
print("There are {0} words in the file.".format(len(words)))


['#', 'Name', 'Email', 'Phone', 'Larry', 'larry@example.com', '111-1111', 'Curly', 'curly@example.com', '222-2222', 'Moe', 'moe@example.com', '333-3333']

There are 13 words in the file.


Пример работы с бинарными файлами:

fin  = open("C:\\projects\\data.txt", "rb")
fout = open("C:\\projects\\data2.txt", "wb")
while True:
    buf = fin.read(1024)
    if len(buf) == 0:
        break
    fout.write(buf)
fin.close()
fout.close()


c:\projects>type data2.txt
# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333



Считать все строки из одного файла и записать все строки кроме тех,
которые начинаются на "#" в другой файл:


def filter(oldfile, newfile):
    infile = open(oldfile, "r")
    outfile = open(newfile, "w")
    while True:
        text = infile.readline()
        if len(text) == 0:
            break
        if text[0] == "#":
            continue
        outfile.write(text)
    infile.close()
    outfile.close()

filter("C:\\projects\\data.txt","C:\\projects\\data3.txt")

c:\projects>type data3.txt
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Считать все строки из файла в список.
Вывести первые два элемента списка (первые две строки):

wordsfile = open("C:\\projects\\data.txt", "r")
wordlist = wordsfile.readlines()
print(wordlist[:2])


['# Name Email Phone\n', 'Larry larry@example.com 111-1111\n']


Другие режимы открытия файлов

Помимо режимов "r" и "w" большинство платформ поддерживает режим "a"

a - append

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


myfile = open("C:\\projects\\data.txt", "w")
myfile.write("# Name Email Phone\n")
myfile.write("Larry larry@example.com 111-1111\n")
myfile.close()
print(open("C:\\projects\\data.txt").read())
myfile.close()


# Name Email Phone
Larry larry@example.com 111-1111


myfile = open("C:\\projects\\data.txt", "a")
myfile.write("Curly curly@example.com 222-2222\n")
myfile.write("Moe moe@example.com 333-3333\n")
myfile.close()
print(open("C:\\projects\\data.txt").read())
myfile.close()


# Name Email Phone
Larry larry@example.com 111-1111
Curly curly@example.com 222-2222
Moe moe@example.com 333-3333


Чаще всего функцию open используют так:

open(имя_файла, режим_открытия, размер_буфера)

обязательный только первый аргумент

По умолчанию:

режим открытия  r
буферизация     полная


Режимы открытия:


r+
файл доступен как для чтения так и для записи, при этом содержимое существующих файлов сохраняется.

w+
файл доступен как для чтения так и для записи, при этом создается файл заново, уничтожая прежнее его содержимое.


rb
читать файл в двоичном режиме

wb
записывать файл в лвоичном режиме


rb+
файл доступен как для чтения так и для записи в двоичном режиме, при этом содержимое существующих файлов сохраняется.

wb+                                                          
файл доступен как для чтения так и для записи в двоичном режиме, при этом создается файл заново, уничтожая прежнее его содержимое.


Проще говоря, по умолчанию используется режим для чтения r, но вы можете использовать режим
w - для записи
a - для дополнения

Можете добавлять символ + , чтобы обеспечить возможность изменения содержимого файла,
а также указывать b и t  чтобы задать двоичный или текстовый режим.

Размер буфера

Функция open принимает необязятельный третий аргумент с размером буфера

0
отсутствие буферизации, данные передаются немедленно,
это значение допустимо только для двоичных режимов

1
построчная буферизация

Любое другое положительное число означает использование режима полной буферизации
этот режим используется по умолчанию


Двоичные и текстовые файлы

Двоичные файлы:

- изображения JPEG
- аудиоклипы
- упакованные двоичные данные


открыть двоичный файл для записи
myfile = open("C:\\projects\\data.txt", "wb")

открыть двоичный файл для чтения
myfile = open("C:\\projects\\data.txt", "rb")

Далее можно использовать стандартные методы:

read
write

Методы readline и readlines как и построчные итераторы файлов,
по прежнему будут работать с текстовыми файлами, открытыми в двоичном режиме.
Но нет никакого смысла применять их к действительно двоичным данным, которые не имеют построчной организации.
(байты \n никакого смысла там не имеют и их может вообще не быть)

Python 3.3.1 (v3.3.1:d9893d13c628, Apr  6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.

>>> open("C:\\projects\\data.txt").read()
'# Name Email Phone\nLarry larry@example.com 111-1111\nCurly curly@example.com 222-2222\nMoe moe@example.com 333-3333\n'
>>>

>>> open("C:\\projects\\data.txt", "rb").read()
b'# Name Email Phone\r\nLarry larry@example.com 111-1111\r\nCurly curly@example.com 222-2222\r\nMoe moe@example.com 333-3333\r\n'
>>>
>>>


>>> myfile = open("C:\\projects\\data.txt", "rb")
>>> for line in myfile:
    print(line)

   
b'# Name Email Phone\r\n'
b'Larry larry@example.com 111-1111\r\n'
b'Curly curly@example.com 222-2222\r\n'
b'Moe moe@example.com 333-3333\r\n'
>>>
>>>


>>> open("C:\\projects\\data.bin", 'wb').write(b'# Name Email Phone\n')
19

>>> open("C:\\projects\\data.bin", 'rb').read()
b'# Name Email Phone\n'
>>>
>>>


>>> open("C:\\projects\\data.bin", 'wb').write('# Name Email Phone\n')
Traceback (most recent call last):
  File "", line 1, in
    open("C:\\projects\\data.bin", 'wb').write('# Name Email Phone\n')
TypeError: 'str' does not support the buffer interface
>>>
аргумент должен быть типа bytes


Кодирование символов Unicode в текстовых файлах

>>> data = 'sp\xe4m'
>>> data
'späm'
>>>
>>> 0xe4, bin(0xe4), chr(0xe4)
(228, '0b11100100', '
ä')
>>>

Закодируем эту строку вручную

>>> data = 'sp\xe4m'
>>> data
'späm'
>>>


>>> 0xe4, bin(0xe4), chr(0xe4)
(228, '0b11100100', '
ä')
>>>


>>> data.encode('latin1')
b'sp\xe4m'
>>>


>>> data.encode('utf8')
b'sp\xc3\xa4m'
>>>


>>> data.encode('ascii')
Traceback (most recent call last):
  File "", line 1, in
    data.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character '\xe4' in position 2: ordinal not in range(128)
>>>


>>> data.encode('utf-16')
b'\xff\xfes\x00p\x00\xe4\x00m\x00'
>>>


>>> data.encode('cp500')
b'\xa2\x97C\x94'
>>>


>>> open("C:\\projects\\data.txt", 'w', encoding='latin1').write(data)
4

>>> open("C:\\projects\\data.txt", 'r', encoding='latin1').read()
'späm'
>>>


>>> open("C:\\projects\\data.txt", 'rb').read()
b'sp\xe4m'
>>>


>>> open("C:\\projects\\data.txt", 'w', encoding='utf8').write(data)
4
>>>


>>> open("C:\\projects\\data.txt", 'r', encoding='utf8').read()
'späm'
>>>


>>> open("C:\\projects\\data.txt", 'rb').read()
b'sp\xc3\xa4m'>>>


>>> open("C:\\projects\\data.txt", 'w', encoding='ascii').write(data)
Traceback (most recent call last):
  File "", line 1, in
    open("C:\\projects\\data.txt", 'w', encoding='ascii').write(data)
UnicodeEncodeError: 'ascii' codec can't encode character '\xe4' in position 2: ordinal not in range(128)
>>>


>>> open(r'C:\Python33\python.exe', 'r').read()
Traceback (most recent call last):
  File "", line 1, in
    open(r'C:\Python33\python.exe', 'r').read()
  File "C:\Python33\lib\encodings\cp1251.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x98 in position 16964: character maps to
>>>


>>> open("C:\\projects\\data.txt", 'w', encoding='cp500').writelines(['spam\n', 'ham\n'])

>>> open("C:\\projects\\data.txt", 'r', encoding='cp500').readlines()
['spam\n', 'ham\n']
>>>


>>> open("C:\\projects\\data.txt", 'r').readlines()
['ў—Ѓ”\n', '%€Ѓ”\n', '%']
>>>


>>> open("C:\\projects\\data.txt", 'rb').readlines()
[b'\xa2\x97\x81\x94\r%\x88\x81\x94\r%']
>>>


>>> open("C:\\projects\\data.txt", 'rb').read()
b'\xa2\x97\x81\x94\r%\x88\x81\x94\r%'
>>>


Имейте ввиду, что текст в кодированном двоичном представлении не может обрабатываться так, как вам хотелось бы.
Текст, закодированный с применением определенной кодировки, не может сравниваться или объединяться с текстом,
закодированным с применением других кодировок.


Преобразование символов конца строки в Windows

Конец строки текста в файле:

\n     в Unix и Linux

\r\n   в Windows


В Python объекты файлов автоматически отображают последовательность DOS \r\n в одиночный символ \n

При выполннии сценариев в Windows:

- для файлов открытых в текстовом режиме, при чтении \r\n преобразуется в \n
  при записи \n  преобразуется в \r\n

- для файлов открытых в двоичном режиме никакие преобразования не производятся.

В UNIX - подобных системах преобразование не производится в любом режиме, т.к. там используется \n

Python скрипт всегда работает с \n
Просто во внешних файлах на платформе Windows он преобразует конец строки в \r\n

Поэтому если на платформе Windows вы ошибочно откроете двоичный файл в текстовом режиме,
то при сохранении вы можете повредить файл, если в файле  случайно втретился символ \n
вы его перезапиите в \r\n
а при чтении \r\n  символ  \r  будет отброшен


>>> open("C:\\projects\\data.txt", 'w').write('shrubbery\n')
10
>>>
\n  преобразован в \r\n


>>> open("C:\\projects\\data.txt", 'rb').read()
b'shrubbery\r\n'
>>>
>>> open("C:\\projects\\data.txt", 'r').read()
'shrubbery\n'
>>>
>>> data = b'a\0b\rc\r\nd'      # 4 байта 4 обычных символа
>>> len(data)
8
>>>

Запись двоичных данных
>>> open("C:\\projects\\data.bin", 'wb').write(data)
8
>>>

Чтение двоичных данных
>>> open("C:\\projects\\data.bin", 'rb').read()
b'a\x00b\rc\r\nd'
>>>
0 - отобразился как шестнадцатеричная последовательность x00


Попробуем прочитать в текстовом режиме:
>>> open("C:\\projects\\data.bin", 'r').read()
'a\x00b\nc\nd'
>>>

символы \r - искажены

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

>>> open("C:\\projects\\data.bin", 'w').write(data)
Traceback (most recent call last):
  File "", line 1, in
    open("C:\\projects\\data.bin", 'w').write(data)
TypeError: must be str, not bytes
>>>

В текстовом режиме должна передаваться строка типа str
Используйте  bytes.decode() для преобразования типа.

>>> data.decode()
'a\x00b\rc\r\nd'
>>> open("C:\\projects\\data.bin", 'w').write(data.decode())
8
>>>


>>> open("C:\\projects\\data.bin", 'rb').read()
b'a\x00b\rc\r\r\nd'
>>>
запись в текстовом режиме добавила символ \r


>>> open("C:\\projects\\data.bin", 'r').read()
'a\x00b\nc\n\nd'
>>>
опять символы \r искажены



Произвольный доступ к данным в файлах

При открытии файлов текущая позиция обычно устанавливается в смещение 0 от начала файла
и перемещается вперед по мере чтения/записи данных.

Метод seek позволяет переместить текущую позицию для следующей операции чтения/записи в другое место,
для чего ему достаточно передать величину смещения в байтах.

seek(n)

seek(n, mode)

mode = 0 абсолютное смещение на n байтов (по умолчанию)
mode = 1 смещение относительно текущей позиции на n байтов
mode = 2 смещение относительно конца файла на n байтов


seek(0)  - перемотать файл в начало (rewind) т.е. текущую позицию переместить в начало файла.


>>> records = [bytes([char]*8) for char in b'mars']
>>> records
[b'mmmmmmmm', b'aaaaaaaa', b'rrrrrrrr', b'ssssssss']
>>>
 


>>> myfile = open("C:\\projects\\random.bin", "w+b")
>>> for rec in records:
    size = myfile.write(rec) # записать 4 записи

   
>>> myfile.flush()
>>> pos = myfile.seek(0)    # прочитать файл целиком


>>> print(myfile.read())
b'mmmmmmmmaaaaaaaarrrrrrrrssssssss'
>>>


Теперь повторно откроем файл в режиме r+b
он также позволяет читать из файла и писать в него,
но не очищает файл при открытии.

>>> myfile = open("C:\\projects\\random.bin", "r+b")
>>> print(myfile.read())    # прочитать файл целиком
b'mmmmmmmmaaaaaaaarrrrrrrrssssssss'
>>>
 

>>> record = b'X' * 8
>>> myfile.seek(0)
0
>>>
 

>>> myfile.write(record)         # изменим первую запись
8
>>>
 

>>> myfile.seek(len(record)*2)
16
>>>
 

>>> myfile.write(b'Y' * 8)       # изменим 3-ю запись
8
>>>
 

>>> myfile.seek(8)
8
>>>
 

>>> myfile.read(len(record))     # извлечем 2-ю запись
b'aaaaaaaa'
>>>
 

>>> myfile.read(len(record))     # извлечем следующую (3-ю) запись
b'YYYYYYYY'
>>>
 

>>> myfile.seek(0)
0
>>>
 

>>> myfile.read()                # прочитать файл целиком
b'XXXXXXXXaaaaaaaaYYYYYYYYssssssss'
>>>


C:\projects>type random.bin
XXXXXXXXaaaaaaaaYYYYYYYYssssssss






Метод seek можно использовать, даже если файл открыт только для чтения.

Пример:

Чтение произвольных записей фиксированной длины.
Используем текстовый режим r
Данные представляют простой текст ASCII, где каждый символ представлен одним байтом
и текст не содержит символов конца строки.

>>> myfile = open("C:\\projects\\random.bin", "r")
>>>

>>> reclen = 8
>>>

>>> myfile.seek(reclen * 3)
24

>>> myfile.read(reclen)         # извлечь 4-ю запись
'ssssssss'
>>>

>>> myfile.seek(reclen * 1)
8

>>> myfile.read(reclen)         # извлечь 2-ю запись
'aaaaaaaa'
>>>


Двоичный режим с таким файлом работает также:

>>> myfile = open("C:\\projects\\random.bin", "rb")
>>>

>>> myfile.seek(reclen * 2)
16

>>> myfile.read(reclen)
b'YYYYYYYY'
>>>



В общем случае текстовый режим не следует использовать, если вам требуется произвольный доступ к записям
(за исключением файлов с простым некодируемым текстом, подобным ASCII, не содержащим символов конца строки)

Пример:

Соответствие между строкой Python и ее кодированным представлением в файле нарушается сразу же за первым не ASCII символом:


>>> data = 'sp\xe4m'

>>> data, len(data)
('späm', 4)

>>> data.encode('utf-8'), len(data.encode('utf-8'))
(b'sp\xc3\xa4m', 5)

Как видим , до кодирования длина строки составляла 4 байта, а после кодирования ее длина стала 5 байтов.
Это существенно осложняет возможность позиционирования по абсолютному смещению.

>>> myfile = open("C:\\projects\\test", mode = "w+", encoding = 'utf8')
>>>

>>> myfile.write(data)
4
>>>

>>> myfile.flush()
>>>

>>> myfile.seek(0); myfile.read(1)
0
's'                                    # для байтов ASCII все OK
>>>

>>> myfile.seek(2); myfile.read(1)
2
'ä'                                    # двухбайтоый не ASCII
>>>

>>> data[3]
'm'                                    # а в смещении 3 не "m" !!!
>>>

>>> myfile.seek(3); myfile.read(1)
3
Traceback (most recent call last):
  File "", line 1, in
    myfile.seek(3); myfile.read(1)
  File "C:\Python33\lib\codecs.py", line 300, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa4 in position 0: invalid start byte
>>>



Пример:

В файл с переводом английских слов, нужно добавить транскрипцию, взяв ее из другого файла:

list.txt

come - приходить                  
get - получить                    
give - давать                     
go - идти                         
keep - держать                    
let - позволять                   
make - сделать                    
put - поместить                   
seem - казаться                   
take - взять                      
be - быть                         

trans.txt

the [ðə:]
think [θiŋk]
or [ɔ:]
got [gɔt]
good [gud]
eye [ai]
before [bi'fɔ:]
long [lɔŋ]
let [let]
take [teik]
saw [sɔ:]
room [ru:m]
place [pleis]
those [ðəuz]
work [wз:k]
put [put]
 

 with open("C:\\test\\list.txt", "r", encoding='utf-8') as f1, open("C:\\test\\trans.txt", "r", encoding='utf-8') as f2, open("C:\\test\\out.txt", "w", encoding='utf-8') as f3:
    for line1 in f1:
        p1 = line1.split()
        f2.seek(0)
        i=0
        for line2 in f2:
            p2 = line2.split()
            if p2 != []:
                if (p2[0].lower() == p1[0].lower()):
                    f3.write("{0:20} {1:20} {2:3} {3:30}\n".format(p1[0],p2[1],p1[1]," ".join(str(x) for x in p1[2:len(p1)])))
                    i+=1
        if i == 0:
            f3.write("{0:20} {1:20} {2:3} {3:30}\n".format(p1[0],"[]",p1[1]," ".join(str(x) for x in p1[2:len(p1)])))







out.txt
 
come                []                   -   приходить                    
get                  []                   -   получить                     
give                 []                   -   давать                       
go                   []                   -   идти                         
keep                 []                   -   держать                      
let                  [let]                -   позволять                    
make                 []                   -   сделать                      
put                  [put]                -   поместить                    
seem                 []                   -   казаться                     
take                 [teik]               -   взять                        
be                   []                   -   быть                         



Или так:

with open("C:\\test\\list.txt", "r", encoding='utf-8-sig') as f1, open("C:\\test\\trans.txt", "r", encoding='utf-8-sig') as f2, open("C:\\test\\out.txt", "w", encoding='utf-8-sig') as f3:
    for line1 in f1:
        p1 = line1.split()
        f2.seek(0)
        i=0
        for line2 in f2:
            p2 = line2.split()
            if p2 != []:
                if (p2[0].lower() == p1[0].lower()):
                    i+=1
                    if i == 1:
                        f3.write("{0:20} {1:20} {2:3} {3:30}\n".format(p1[0],p2[1],p1[1]," ".join(str(x) for x in p1[2:len(p1)])))
        if i == 0:
            f3.write("{0:20} {1:20} {2:3} {3:30}\n".format(p1[0],"[]",p1[1]," ".join(str(x) for x in p1[2:len(p1)])))



воскресенье, 21 июля 2013 г.

DATABASE LINK

Получить метаданные о линке:

SELECT DBMS_METADATA.GET_DDL('DB_LINK',a.db_link,a.owner) || '/' FROM dba_db_links a


Создать линк:

CREATE DATABASE LINK "MY_LINK.SUN.COM"
   CONNECT TO "SCOTT" IDENTIFIED BY VALUES '054B287C5C9D0928639F28CC53F9D6D5043A07D0BE8325534D'
   USING 'TESTDB_REMOTEDB.MSK.SUN.COM'


Удалить линк:

SELECT   'DROP PUBLIC DATABASE LINK ' || object_name ||';'
FROM     SYS.dba_objects
where    object_type = 'DATABASE LINK'
and      owner = 'PUBLIC';


Просмотр информации о линках:

select * from dba_db_links;

select * from dba_objects  where object_type like '%DATABASE LINK%'

select * from sys.v_$dblink;


Проверяем что линк работает:

select * from dual@MY_LINK.SUN.COM;
select * from all_tables@MY_LINK.SUN.COM;
select * from  t1@MY_LINK.SUN.COM;



Работать с линками так:

select * from  t1@MY_LINK.SUN.COM;
rollback;
alter session close database link MY_LINK.SUN.COM;
select * from sys.v_$dblink;
select * from  t1@MY_LINK.SUN.COM;




database links (distributed transaction)



set lines 400
column origin format a45
column GTXID format a50
column LSESSION format a10
column USERNAME format a10
column status format a1
column waiting format a30

select /*+ ordered */ substr(s.ksusemnm,1,35)||'-'|| substr(s.ksusepid,1,35) origin,
substr(g.k2gtitid_ora,1,50) gtxid,
substr(s.indx,1,4)||'.'|| substr(s.ksuseser,1,5) lsession,
s.ksuudlna username,
substr(decode(bitand(ksuseidl,11), 1,'ACTIVE', 0, decode( bitand(ksuseflg,4096) , 0,'INACTIVE','CACHED'), 2,'SNIPED', 3,'SNIPED', 'KILLED'),1,1) status,
e.kslednam waiting
from x$k2gte g, x$ktcxb t, x$ksuse s, x$ksled e
where g.k2gtdxcb=t.ktcxbxba
and g.k2gtdses=t.ktcxbses
and s.addr=g.k2gtdses
and e.indx=s.ksuseopc;



ORIGIN = Machine-PID, машина, на которой работает клиентский инструмент

C eis-web.sun.ru process PID=1234 подключился к нашей базе (SPROM) под пользователем QRUSER


На SPROM

ORIGIN                                                                                                     GTXID             LSESSION         USERNAME    S     WAITING                       
----------------------------------------- ---------------------------------------------            -----------          ----------        -      ------------------------------
eis-web.sun.ru-1234                SPROM.b39bc3cb.23.4.3947425                19.45953           QRUSER          I      SQL*Net message from client   

На ARCH

ORIGIN                                                                                                      GTXID               LSESSION         USERNAME   S        WAITING                       
----------------------------------------- ---------------------------------------------             -------------      ----------       -        ------------------------------
base00dbadm01.domain.corp-88840      SPROM.b39bc3cb.23.4.3947425                1853.31078       ARCHIVE       I         SQL*Net message from client   

Далее порождённый процесс PID=88840 с базы (SPROM)  по dblink подключается к нашей базе (ARCH) под пользователем ARCH.
Причём GTXID (глобальный идентификатор транзакции), у них один (SPROM.b39bc3cb.23.4.3947425) и порождёна эта транзакция была в базе SPROM.

LSESSION  (Local Session),
это сеанс в вашей локальной базе данных (к которой вы подключены и запускаете этот скрипт)

S = статус LSESSION, он имеет 1 букву со следующим значением:

I (inactive)    
A (active)
C (cached)
S (sniped)
K (killed)

           
WAITING (чего ждет LSESSION)



(This SQL was posted to Metalink, now officially in Doc Note:104420.1.)





Метаданные Oracle


Метаданные DATABASE LINK:

SELECT DBMS_METADATA.GET_DDL('DB_LINK',a.db_link,a.owner) || '/' FROM dba_db_links a


Получить метаданные пользователя ANGOR:

set feedback off
set pagesize 25000
set linesize 1000
set long 90000
column script format a1000
set serveroutput on

variable v_username VARCHAR2(30);
exec :v_username := upper('angor');

--This line add a semicolon at the end of each statement
execute dbms_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SQLTERMINATOR',true);

-- This will generate the DDL for the user and add his objects,system and role grants
SELECT DBMS_METADATA.GET_DDL('USER',username) as script from DBA_USERS where username= :v_username
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('SYSTEM_GRANT',grantee) as script from DBA_SYS_PRIVS where grantee= :v_username and rownum=1
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('ROLE_GRANT',grantee) as script from DBA_ROLE_PRIVS where grantee= :v_username and rownum=1
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('OBJECT_GRANT',grantee) as script from DBA_TAB_PRIVS where grantee= :v_username and rownum=1;



clear screen
SET LONG 20000
SET LONGCHUNKSIZE 20000
SET PAGESIZE 0
SET LINESIZE 1000
SET FEEDBACK OFF
SET VERIFY OFF
SET TRIMSPOOL ON
column script format a1000
set serveroutput on

variable v_username VARCHAR2(30);
exec :v_username := upper('angor');

BEGIN
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SQLTERMINATOR', true);
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'PRETTY', true);
END;
/

SELECT dbms_metadata.get_ddl('USER', :v_username) as script FROM dual
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('SYSTEM_GRANT', :v_username) as script from dual
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('ROLE_GRANT', :v_username) as script from dual
UNION ALL
SELECT DBMS_METADATA.GET_GRANTED_DDL('OBJECT_GRANT', :v_username) as script from dual;

spool off



set long 20000
set longchunksize 20000
set pagesize 25000
set linesize 1000
set feedback off
set verify off
set trimspool on
column ddl format a1000

begin
   dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SQLTERMINATOR', true);
   dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'PRETTY', true);
end;
/

variable v_username VARCHAR2(30);
exec :v_username := upper('angor');

select dbms_metadata.get_ddl('USER', u.username) AS ddl
from   dba_users u
where  u.username = :v_username
union all
select dbms_metadata.get_granted_ddl('TABLESPACE_QUOTA', tq.username) AS ddl
from   dba_ts_quotas tq
where  tq.username = :v_username
and    rownum = 1
union all
select dbms_metadata.get_granted_ddl('ROLE_GRANT', rp.grantee) AS ddl
from   dba_role_privs rp
where  rp.grantee = :v_username
and    rownum = 1
union all
select dbms_metadata.get_granted_ddl('SYSTEM_GRANT', sp.grantee) AS ddl
from   dba_sys_privs sp
where  sp.grantee = :v_username
and    rownum = 1
union all
select dbms_metadata.get_granted_ddl('OBJECT_GRANT', tp.grantee) AS ddl
from   dba_tab_privs tp
where  tp.grantee = :v_username
and    rownum = 1
union all
select dbms_metadata.get_granted_ddl('DEFAULT_ROLE', rp.grantee) AS ddl
from   dba_role_privs rp
where  rp.grantee = :v_username
and    rp.default_role = 'YES'
and    rownum = 1
union all
select to_clob('/* Start profile creation script in case they are missing') AS ddl
from   dba_users u
where  u.username = :v_username
and    u.profile <> 'DEFAULT'
and    rownum = 1
union all
select dbms_metadata.get_ddl('PROFILE', u.profile) AS ddl
from   dba_users u
where  u.username = :v_username
and    u.profile <> 'DEFAULT'
union all
select to_clob('End profile creation script */') AS ddl
from   dba_users u
where  u.username = :v_username
and    u.profile <> 'DEFAULT'
and    rownum = 1
/






вторник, 16 июля 2013 г.

Настройка ACL

В Oracle11g  для любого пакета, выполняющего внешние сетевые вызовы  (UTL_SMTP, UTL_MAIL) необходимо создать список ACL, включить в него пользователя или роль и предоставить списку привилегию сетевого уровня.

Посмотреть, есть ли какие-либо ACL в базе можно так:

select acl , host , lower_port , upper_port from DBA_NETWORK_ACLS;

  Создаем список ACL, включаем в него пользователя  и предоставляем списку привилегию сетевого уровня:

begin
    dbms_network_acl_admin.create_acl(
        acl                  => 'mail-server.xml'
        ,description    => 'Permission to make connections to mail server'
        ,principal       => 'SCOTT'
        ,is_grant        => TRUE
        ,privilege       => 'connect'
    );
    dbms_network_acl_admin.assign_acl(
        acl                  => 'mail-server.xml'
        ,host               => 'my-SMTP-servername'
        ,lower_port    => 25
        ,upper_port   => NULL /* открывается только порт 25*/
    );
end;


ещё пример:

begin
    -- Создание списка ACL
    dbms_network_acl_admin.create_acl(
        acl                  =>  'oracle-permissions.xml'
        ,description    => 'Network permissions for www.oracle.com'
        ,principal       => 'WEBROLE'
        ,is_grant        => TRUE
        ,privilege       => 'connect'
        ,start_date      => SYSTIMESTAMP
        ,end_date       => NULL
    );
    -- Назначение привилегий
    dbms_network_acl_admin.create_acl(
        acl                  => 'oracle-permissions.xml'
        ,description    => 'Network permissions for www.oracle.com'
        ,principal       => 'WEDROLE'
        ,is_grant        => TRUE
        ,privilege       => 'connect'
        ,start_date      => SYSTIMESTAMP
        ,end_date       => NULL
    );
     -- Определение допустимых адресов
    dbms_network_acl_admin.assign_acl(
        acl                  => 'oracle-permissions.xml'
        ,host               => 'www.oracle.com'
        ,lower_port    =>80
        ,upper_port   => 80
    );
end;



Еще пример:

DECLARE
  l_acl_name         VARCHAR2(30) := 'utl_tcp.xml';
  l_ftp_server_ip    VARCHAR2(20) := '192.168.0.1';
  l_ftp_server_name  VARCHAR2(20) := 'ftp.oracle.com';
  l_username         VARCHAR2(30) := 'SCOTT';
BEGIN
  DBMS_NETWORK_ACL_ADMIN.create_acl (
    acl          => l_acl_name, 
    description  => 'Allow connections using UTL_TCP',
    principal    => l_username,
    is_grant     => TRUE, 
    privilege    => 'connect',
    start_date   => SYSTIMESTAMP,
    end_date     => NULL);

  COMMIT;

  DBMS_NETWORK_ACL_ADMIN.add_privilege ( 
    acl         => l_acl_name, 
    principal   => l_username,
    is_grant    => FALSE, 
    privilege   => 'connect', 
    position    => NULL, 
    start_date  => NULL,
    end_date    => NULL);

  COMMIT;

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => l_acl_name,
    host        => l_ftp_server_ip, 
    lower_port  => NULL,
    upper_port  => NULL);

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => l_acl_name,
    host        => l_ftp_server_name, 
    lower_port  => NULL,
    upper_port  => NULL);

  COMMIT;
END;
/


Можно использовать пакет:

create or replace package    "pkg_DBA_IR"
AUTHID CURRENT_USER
is
     procedure change_assign_acl;
end  "pkg_DBA_IR";


create or replace package body    "pkg_DBA_IR" is
  --
  -- Константы:
  --
 
  -- Имена баз данных:
  C_DB_NAME_PROD constant varchar2(30) := 'TEST';
  C_DB_NAME_UAT    constant varchar2(30) := 'TESTUAT';
  C_DB_NAME_DEV   constant varchar2(30) := 'TESTDEV';
 

  -- Имена хостов:
  C_HOST_NAME_PROD constant varchar2(30) := 'esbprod.sun.com';
  C_HOST_NAME_UAT    constant varchar2(30) := 'esbuat.sun.com';
  C_HOST_NAME_DEV   constant varchar2(30) := 'esbdev.sun.com';
 
 
  -- Имена параметров:
  C_ACL_NAME       constant varchar2(30) :='networkacl.xml';
 
  -- Смена параметров ACL:
  procedure change_assign_acl
  is
  begin
    if upper(SYS_CONTEXT ('USERENV', 'DB_NAME')) = C_DB_NAME_PROD then
      raise_application_error(-20001, 'Run Only in Test Environment');
   
    elsif upper(SYS_CONTEXT ('USERENV', 'DB_NAME')) = C_DB_NAME_UAT then

      begin
       dbms_network_acl_admin.drop_acl(
       acl          => C_ACL_NAME);               
       dbms_output.put_line('ACL dropped…..');
       exception
        when others then
        dbms_output.put_line('Error dropping ACL: '||C_ACL_NAME);
        dbms_output.put_line(sqlerrm);
      end;

      begin
       dbms_network_acl_admin.create_acl(
       acl          => C_ACL_NAME,
       description  => 'Permissions to access WebServices',
       principal    => 'TS',
       is_grant     => TRUE,
       privilege    => 'connect');
       dbms_output.put_line('ACL created…..');
       exception
        when others then
        dbms_output.put_line('Error creating ACL: '||C_ACL_NAME);
        dbms_output.put_line(sqlerrm);
      end;

      begin
       dbms_network_acl_admin.assign_acl(
       acl          => C_ACL_NAME,               
       host         => C_HOST_NAME_UAT,
       lower_port => NULL,
       upper_port => NULL);
       dbms_output.put_line('ACL assigned…..');
       exception
       when others then
       dbms_output.put_line('Error assigning ACL: '||C_ACL_NAME);
       dbms_output.put_line(sqlerrm);
      end;

      commit;

    elsif upper(SYS_CONTEXT ('USERENV', 'DB_NAME')) = C_DB_NAME_DEV then

      begin
       dbms_network_acl_admin.drop_acl(
       acl          => C_ACL_NAME);               
       dbms_output.put_line('ACL dropped…..');
       exception
        when others then
        dbms_output.put_line('Error dropping ACL: '||C_ACL_NAME);
        dbms_output.put_line(sqlerrm);
      end;

      begin
       dbms_network_acl_admin.create_acl(
       acl          => C_ACL_NAME,
       description  => 'Permissions to access WebServices',
       principal    => 'TS',
       is_grant     => TRUE,
       privilege    => 'connect');
       dbms_output.put_line('ACL created…..');
       exception
        when others then
        dbms_output.put_line('Error creating ACL: '||C_ACL_NAME);
        dbms_output.put_line(sqlerrm);
      end;

      begin
       dbms_network_acl_admin.assign_acl(
       acl          => C_ACL_NAME,               
       host         => C_HOST_NAME_DEV,
       lower_port => NULL,
       upper_port => NULL);
       dbms_output.put_line('ACL assigned…..');
       exception
       when others then
       dbms_output.put_line('Error assigning ACL: '||C_ACL_NAME);
       dbms_output.put_line(sqlerrm);
      end;

      commit;

    else
      commit;

    end if;

  exception
    when others then
      null;
  end change_assign_acl;

end "pkg_DBA_IR";



grant execute on dbms_network_acl_admin TO ts;


begin
  TS."pkg_DBA_IR".change_assign_acl;
end;
/