Показаны сообщения с ярлыком Python. Показать все сообщения
Показаны сообщения с ярлыком Python. Показать все сообщения

понедельник, 8 сентября 2014 г.

Установка пакета cx_Oracle

1. Устанавливаем Oracle Client


2. Выставляем переменные окружения


[angor@omega admin]$ export ORACLE_HOME=/u01/app/oracle/product/12.1.0/client_1
[angor@omega admin]$ export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
[angor@omega admin]$ export PATH=$ORACLE_HOME/bin:$PATH

3. Устанавливаем  cx_oracle


[angor@omega admin]$ sudo easy_install cx_oracle

4. Проверяем


[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>>


import cx_Oracle
ip = '192.168.0.1'
port = 1521
SID = 'YOURSIDHERE'
dsn_tns = cx_Oracle.makedsn(ip, port, SID)
db = cx_Oracle.connect('username', 'password', dsn_tns)


import cx_Oracle
connstr = 'scott/tiger@server:1521/orcl'
conn = cx_Oracle.connect(connstr)


import cx_Oracle
CONN_INFO = {
    'host': '192.168.0.1',
    'port': 1521,
    'user': 'user_name',
    'psw': 'your_password',
    'service': 'my_service',
}
CONN_STR = '{user}/{psw}@{host}:{port}/{service}'.format(**CONN_INFO)
connection = cx_Oracle.connect(CONN_STR)


import cx_Oracle
ip = '192.168.0.1'
port = 1521
service_name = 'my_service'
dsn = cx_Oracle.makedsn(ip, port, service_name=service_name)
db = cx_Oracle.connect('user', 'password', dsn)


import cx_Oracle
dsn = cx_Oracle.makedsn(host='127.0.0.1', port=1521, sid='your_sid')
conn = cx_Oracle.connect(user='angor', password='password', dsn=dsn)
conn.close()


import cx_Oracle
ip = '192.168.0.1'
port = 1524
SID = 'dev3'
dsn_tns = cx_Oracle.makedsn(ip, port, SID)
conn = cx_Oracle.connect('angor', 'pass', dsn_tns)
print conn.version
conn.close()


Пример:

test_ora.py

import sys
import getpass
import platform
import cx_Oracle

# Версии Python и модулей

print ("Python version: " + platform.python_version())
print ("cx_Oracle version: " + cx_Oracle.version)
print ("Oracle client: " + str(cx_Oracle.clientversion()).replace(', ','.'))
print ('-' * 90)

# Приконнектимся к Oracle

username = 'scott'
pwd = 'tiger'
database = 'testdb'
connection = cx_Oracle.connect(username, pwd, database)

# Или так:
#connection = cx_Oracle.connect('scott', 'tiger', 'testdb')
#connection = cx_Oracle.connect('scott/tiger@testdb')


# Некоторые атрибуты объекта connection:
print ("Oracle DB version: " + connection.version)
print ("Oracle client encoding: " + connection.encoding)
print ('-' * 90)


# Создадим курсор и выполним запрос к БД:

cursor = connection.cursor()
query = "select * from v$version"

cursor.execute(query)
rows = cursor.fetchall()

for row in rows:
    print(row)

connection.close()

C:\project\py>test_ora.py

Python version: 3.5.1
cx_Oracle version: 5.2
Oracle client: (12.1.0.2.0)
------------------------------------------------------------------------------------------
Oracle DB version: 12.1.0.2.0
Oracle client encoding: WINDOWS-1252
------------------------------------------------------------------------------------------
('Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production', 0)
('PL/SQL Release 12.1.0.2.0 - Production', 0)
('CORE\t12.1.0.2.0\tProduction', 0)
('TNS for 64-bit Windows: Version 12.1.0.2.0 - Production', 0)
('NLSRTL Version 12.1.0.2.0 - Production', 0)

C:\project\py>


Ещё способы создания объектов соединений с БД Oracle:



import cx_Oracle

#lsnrctl servises
service = 'testdb.localdomain'


connection = cx_Oracle.connect('scott', 'tiger', 'localhost:1521/' + service)


connection = cx_Oracle.connect('scott/tiger@localhost:1521/' + service)


dsn_tns = cx_Oracle.makedsn('localhost', 1521, service).replace('SID','SERVICE_NAME')

print(dsn_tns)

(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=testdb.localdomain)))
 
connection = cx_Oracle.connect('scott', 'tiger', dsn_tns)



Пример создания таблицы:

DROP TABLE EMP;

CREATE TABLE EMP(
    EMPNO NUMBER(4) NOT NULL,
    ENAME VARCHAR2(10),
    JOB VARCHAR2(9),
    MGR NUMBER(4),
    HIREDATE DATE,
    SAL NUMBER(7, 2),
    COMM NUMBER(7, 2),
    DEPTNO NUMBER(2)
);

alter session set nls_date_format='DD-MON-YYYY';
alter session set nls_language=AMERICAN;


INSERT INTO EMP VALUES(7369, 'SMITH',  'CLERK',     7902,TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800,  NULL, 20);
INSERT INTO EMP VALUES(7499, 'ALLEN',  'SALESMAN',  7698,TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300,  30);
INSERT INTO EMP VALUES(7521, 'WARD',   'SALESMAN',  7698,TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500,  30);
INSERT INTO EMP VALUES(7566, 'JONES',  'MANAGER',   7839,TO_DATE('2-APR-1981',  'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES(7654, 'MARTIN', 'SALESMAN',  7698,TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES(7698, 'BLAKE',  'MANAGER',   7839,TO_DATE('1-MAY-1981',  'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES(7782, 'CLARK',  'MANAGER',   7839,TO_DATE('9-JUN-1981',  'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES(7788, 'SCOTT',  'ANALYST',   7566,TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES(7839, 'KING',   'PRESIDENT', NULL,TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES(7844, 'TURNER', 'SALESMAN',  7698,TO_DATE('8-SEP-1981',  'DD-MON-YYYY'), 1500, 0,    30);
INSERT INTO EMP VALUES(7876, 'ADAMS',  'CLERK',     7788,TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES(7900, 'JAMES',  'CLERK',     7698,TO_DATE('3-DEC-1981',  'DD-MON-YYYY'), 950,  NULL, 30);
INSERT INTO EMP VALUES(7902, 'FORD',   'ANALYST',   7566,TO_DATE('3-DEC-1981',  'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES(7934, 'MILLER', 'CLERK',     7782,TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);



С использованием cx_Oracle:

import cx_Oracle

connection = cx_Oracle.connect('scott/tiger@testdb')

cursor = connection.cursor()

try:
    cursor.execute("DROP TABLE EMP")
except:
    print('Таблица не существует')


create_table = """
CREATE TABLE EMP(
    EMPNO NUMBER(4) NOT NULL,
    ENAME VARCHAR2(10),
    JOB VARCHAR2(9),
    MGR NUMBER(4),
    HIREDATE DATE,
    SAL NUMBER(7, 2),
    COMM NUMBER(7, 2),
    DEPTNO NUMBER(2))
"""

cursor.execute(create_table)

cursor.execute("alter session set nls_date_format='DD-MON-YYYY'")
cursor.execute("alter session set nls_language=AMERICAN")
  
cursor.execute("INSERT INTO EMP VALUES(7369, 'SMITH', 'CLERK', 7902,TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20)")
cursor.execute("INSERT INTO EMP VALUES(7499, 'ALLEN', 'SALESMAN', 7698,TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30)")
cursor.execute("INSERT INTO EMP VALUES(7521, 'WARD', 'SALESMAN', 7698,TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30)")
cursor.execute("INSERT INTO EMP VALUES(7566, 'JONES', 'MANAGER', 7839,TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20)")
cursor.execute("INSERT INTO EMP VALUES(7654, 'MARTIN', 'SALESMAN', 7698,TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30)")
cursor.execute("INSERT INTO EMP VALUES(7698, 'BLAKE', 'MANAGER', 7839,TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30)")
cursor.execute("INSERT INTO EMP VALUES(7782, 'CLARK', 'MANAGER', 7839,TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10)")
cursor.execute("INSERT INTO EMP VALUES(7788, 'SCOTT', 'ANALYST', 7566,TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20)")
cursor.execute("INSERT INTO EMP VALUES(7839, 'KING', 'PRESIDENT', NULL,TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10)")
cursor.execute("INSERT INTO EMP VALUES(7844, 'TURNER', 'SALESMAN', 7698,TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30)")
cursor.execute("INSERT INTO EMP VALUES(7876, 'ADAMS', 'CLERK', 7788,TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20)")
cursor.execute("INSERT INTO EMP VALUES(7900, 'JAMES', 'CLERK', 7698,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30)")
cursor.execute("INSERT INTO EMP VALUES(7902, 'FORD', 'ANALYST', 7566,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20)")
cursor.execute("INSERT INTO EMP VALUES(7934, 'MILLER', 'CLERK', 7782,TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10)")

connection.commit()

query = "select * from emp"

cursor.execute(query)
rows = cursor.fetchall()

for row in rows:
    print(row)

print ('-' * 90)

query1 = "select empno, ename, to_char(hiredate,'dd.mm.yyyy hh24:mi:ss') from emp"

cursor.execute(query1)
rows = cursor.fetchall()

for row in rows:
    print(row)
  

drop_table = "delete from emp"
cursor.execute(drop_table)
connection.commit()

cursor.execute(query)
rows = cursor.fetchall()

for row in rows:
    print(row)

connection.close()


(7369, 'SMITH', 'CLERK', 7902, datetime.datetime(1980, 12, 17, 0, 0), 800.0, None, 20)
(7499, 'ALLEN', 'SALESMAN', 7698, datetime.datetime(1981, 2, 20, 0, 0), 1600.0, 300.0, 30)
(7521, 'WARD', 'SALESMAN', 7698, datetime.datetime(1981, 2, 22, 0, 0), 1250.0, 500.0, 30)
(7566, 'JONES', 'MANAGER', 7839, datetime.datetime(1981, 4, 2, 0, 0), 2975.0, None, 20)
(7654, 'MARTIN', 'SALESMAN', 7698, datetime.datetime(1981, 9, 28, 0, 0), 1250.0, 1400.0, 30)
(7698, 'BLAKE', 'MANAGER', 7839, datetime.datetime(1981, 5, 1, 0, 0), 2850.0, None, 30)
(7782, 'CLARK', 'MANAGER', 7839, datetime.datetime(1981, 6, 9, 0, 0), 2450.0, None, 10)
(7788, 'SCOTT', 'ANALYST', 7566, datetime.datetime(1982, 12, 9, 0, 0), 3000.0, None, 20)
(7839, 'KING', 'PRESIDENT', None, datetime.datetime(1981, 11, 17, 0, 0), 5000.0, None, 10)
(7844, 'TURNER', 'SALESMAN', 7698, datetime.datetime(1981, 9, 8, 0, 0), 1500.0, 0.0, 30)
(7876, 'ADAMS', 'CLERK', 7788, datetime.datetime(1983, 1, 12, 0, 0), 1100.0, None, 20)
(7900, 'JAMES', 'CLERK', 7698, datetime.datetime(1981, 12, 3, 0, 0), 950.0, None, 30)
(7902, 'FORD', 'ANALYST', 7566, datetime.datetime(1981, 12, 3, 0, 0), 3000.0, None, 20)
(7934, 'MILLER', 'CLERK', 7782, datetime.datetime(1982, 1, 23, 0, 0), 1300.0, None, 10)
------------------------------------------------------------------------------------------
(7369, 'SMITH', '17.12.1980 00:00:00')
(7499, 'ALLEN', '20.02.1981 00:00:00')
(7521, 'WARD', '22.02.1981 00:00:00')
(7566, 'JONES', '02.04.1981 00:00:00')
(7654, 'MARTIN', '28.09.1981 00:00:00')
(7698, 'BLAKE', '01.05.1981 00:00:00')
(7782, 'CLARK', '09.06.1981 00:00:00')
(7788, 'SCOTT', '09.12.1982 00:00:00')
(7839, 'KING', '17.11.1981 00:00:00')
(7844, 'TURNER', '08.09.1981 00:00:00')
(7876, 'ADAMS', '12.01.1983 00:00:00')
(7900, 'JAMES', '03.12.1981 00:00:00')
(7902, 'FORD', '03.12.1981 00:00:00')
(7934, 'MILLER', '23.01.1982 00:00:00')
 
 

Подключение к базам в цикле:

 
database.csv

sid;pwdsys;uconn;host
TESTDB;oracle;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=omega)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTDB_OMEGA)));omega
TESTDB;oracle;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=omega)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTDB_OMEGA)));omega
TESTDB;oracle;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=omega)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTDB_OMEGA)));omega
TESTDB;oracle;DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=omega)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTDB_OMEGA)));omega
TESTDB;oracle;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=omega)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTDB_OMEGA)));omega


import cx_Oracle
import pandas as pd
import numpy as np

data = pd.read_csv('database.csv', sep=';')
data_rows, data_columns = data.shape


for i in range(data_rows):
    sid = data.loc[i,'sid']
    pwd = data.loc[i,'pwdsys']
    conn = data.loc[i,'uconn']
    s = 'sys/'+pwd+'@'+conn
    #print(s)
    try:
        ora_conn = cx_Oracle.connect(s, mode = cx_Oracle.SYSDBA)
        cursor = ora_conn.cursor()
        query = "select * from dual"
        cursor.execute(query)
        rows = cursor.fetchall()
        for row in rows:
            print(row)
    except cx_Oracle.DatabaseError as e:
        error, = e.args
        if error.code == 1017:
            print('Please check your credentials. {}'.format(e))
        else:
            print('Database connection error: {}'.format(e))
            
    finally:
        try:
            cursor.close()           
            ora_conn.close()
        except:
            print('cx_Oracle.connect or db.cursor')


('X',)
('X',)
('X',)
Database connection error: ORA-12154: TNS:could not resolve the connect identifier specified
cx_Oracle.connect or db.cursor
('X',)

 
 
 
username = 'angor'
password = ''
dsn = 'localhost/pdborcl'
port = 1512
encoding = 'UTF-8'

import cx_Oracle
import config
 
sql = 'select customer_id, name ' \
      'from customers ' \
      'order by name'
try:
    with cx_Oracle.connect(
                config.username,
                config.password,
                config.dsn,
                encoding=config.encoding) as connection:
        #fetchone 
        with connection.cursor() as cursor:
            cursor.execute(sql)
            while True:
                row = cursor.fetchone()
                if row is None:
                    break
                print(row)
except cx_Oracle.Error as error:
    print(error)



        #fetchall
        with connection.cursor() as cursor:
            # execute the SQL statement
            cursor.execute(sql)
            # fetch all rows
            rows = cursor.fetchall()
            if rows:
                for row in rows:
                    print(row)
except cx_Oracle.Error as error:
    print(error)




batch_size = 20

        #fetchmany
        with connection.cursor() as cursor:
            # execute the SQL statement
            cursor.execute(sql)
            while True:
                # fetch rows
                rows = cursor.fetchmany(batch_size)
                if not rows:
                    break
                # display rows
                for row in rows:
                    print(row)
except cx_Oracle.Error as error:
    print(error)
 
 
 
Существует четыре типа больших объектов:
BLOB - Большой двоичный объект, используемый для хранения двоичных данных. cx_Oracle использует тип cx_Oracle.BLOB.
CLOB - Большой символьный объект, используемый для символьных строк в формате набора символов базы данных. cx_Oracle использует тип cx_Oracle.CLOB.
NCLOB - большой объект национального символа, используемый для символьных строк в формате набора национальных символов. cx_Oracle использует тип cx_Oracle.NCLOB.
BFILE - внешний двоичный файл, используемый для ссылки на файл, хранящийся в операционной системе хоста за пределами базы данных. cx_Oracle использует тип cx_Oracle.BFILE.

Большие объекты могут передаваться в Oracle Database и из нее.
Большие объекты длиной до 1 ГБ также могут обрабатываться непосредственно как строки или байты в cx_Oracle.
Это облегчает работу с большими объектами и дает значительные преимущества в производительности по сравнению с потоковой передачей.
Однако для этого требуется, чтобы все данные больших объектов присутствовали в памяти Python, что может быть невозможно.
Смотрите GitHub для примеров LOB.
Простая вставка больших объектов

Рассмотрим таблицу со столбцами CLOB и BLOB:

CREATE TABLE lob_tbl (
    id NUMBER,
    c CLOB,
    b BLOB
);

С помощью cx_Oracle данные больших объектов могут быть вставлены в таблицу путем привязки строк или байтов по мере необходимости:

with open('example.txt', 'r') as f:
    textdata = f.read()

with open('image.png', 'rb') as f:
    imgdata = f.read()

cursor.execute("""
        insert into lob_tbl (id, c, b)
        values (:lobid, :clobdata, :blobdata)""",
        lobid=10, clobdata=textdata, blobdata=imgdata)

Обратите внимание, что при таком подходе размер больших данных ограничен 1 ГБ.
Извлечение больших объектов в виде строк и байтов
CLOB и BLOB размером менее 1 ГБ могут запрашиваться из базы данных напрямую в виде строк и байтов.
Это может быть намного быстрее, чем потоковое.
Необходимо использовать Connection.outputtypehandler или Cursor.outputtypehandler, как показано в этом примере:

def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
    if defaultType == cx_Oracle.CLOB:
        return cursor.var(cx_Oracle.LONG_STRING, arraysize=cursor.arraysize)
    if defaultType == cx_Oracle.BLOB:
        return cursor.var(cx_Oracle.LONG_BINARY, arraysize=cursor.arraysize)

id_v = 1
textData = "Текстовые данные"
bytesData = b"Бинарные данные"
cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
        [id_v, textData, bytesData])

connection.outputtypehandler = OutputTypeHandler
cursor.execute("select c, b from lob_tbl where id = :1", [id_v])
clobData, blobData = cursor.fetchone()
print("CLOB length:", len(clobData))
print("CLOB data:", clobData)
print("BLOB length:", len(blobData))
print("BLOB data:", blobData)


Без обработчика типа вывода значения CLOB и BLOB извлекаются как объекты LOB.
Размер объекта LOB можно получить, вызвав LOB.size (), а данные можно прочитать, вызвав LOB.read ():

id_v = 1
textData = "Текстовые данные"
bytesData = b"Бинарные данные"
cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
        [id_v, textData, bytesData])

cursor.execute("select b, c from lob_tbl where id = :1", [id_v])
b, c = cursor.fetchone()
print("CLOB length:", c.size())
print("CLOB data:", c.read())
print("BLOB length:", b.size())
print("BLOB data:", b.read())

Этот подход дает те же результаты, что и в предыдущем примере, но он будет работать медленнее
потому что это требует большего количества обращений к базе данных Oracle и имеет более высокие издержки.
 
 
 
Читать большие BLOB объекты можно с помощью метода LOB.read().
Метод LOB.read() может вызываться повторно до тех пор, 
пока не будут прочитаны все данные


cursor.execute("select b from lob_t where id = :1", [10])
blob, = cursor.fetchone()
offset = 1
numBytesInChunk = 65536
with open("image.png", "wb") as f:
    while True:
        data = blob.read(offset, numBytesInChunk)
        if data:
            f.write(data)
        if len(data) < numBytesInChunk:
            break
        offset += len(data)
 
 
Записывать большие BLOB объекты можно с помощью метода BLOB.write():

id_v = 9
lob_v = cursor.var(cx_Oracle.BLOB)
cursor.execute("""
        insert into lob_tbl (id, b)
        values (:1, empty_blob())
        returning b into :2""", [id_v, lob_v])
blob, = lob_v.getvalue()
offset = 1
numBytesInChunk = 65536
with open("image.png", "rb") as f:
    while True:
        data = f.read(numBytesInChunk)
        if data:
            blob.write(data, offset)
        if len(data) < numBytesInChunk:
            break
        offset += len(data)
connection.commit()
 
 
 
 
 

Соответствие типов данных :

 
Oracle cx_Oracle Python
VARCHAR2
NVARCHAR2
LONG
cx_Oracle.STRING str
CHAR cx_Oracle.FIXED_CHAR
NUMBER cx_Oracle.NUMBER int
FLOAT float
DATE cx_Oracle.DATETIME datetime.datetime
TIMESTAMP cx_Oracle.TIMESTAMP
CLOB cx_Oracle.CLOB cx_Oracle.LOB
BLOB cx_Oracle.BLOB


Some quick syntax reminders for common tasks using DB-API2 modules.
task
postgresql
sqlite
MySQL
Oracle
ODBC
oursql
create database
createdb mydb
created automatically when opened with sqlite3
 
created with Oracle XE install
 
 
command-line tool
psql -d mydb
sqlite3 mydb.sqlite
mysql testdb
sqlplus scott/tiger
 
 
GUI tool
pgadmin3
 
mysql-admin
sqldeveloper
 
 
install module
easy_install psycopg2
included in Python 2.5 standard library
easy_install mysql-python or apt-get install python-mysqldb
easy_install cx_oracle (but see note)
 
 
import
from psycopg2 import *
from sqlite3 import *
from MySQLdb import *
from cx_Oracle import *
 
 
connect
conn = connect("dbname='testdb' user='me' host='localhost' password='mypassword'”)
conn = connect('mydb.sqlite') or conn=connect(':memory:')
conn = connect (host="localhost", db="testdb", user="me", passwd="mypassword")
conn=connect('scott/tiger@xe')
conn = odbc.odbc('DBALIAS') or odbc.odbc('DBALIAS/USERNAME/PASSWORD')
 
get cursor
curs = conn.cursor()
curs = conn.cursor()
curs = conn.cursor()
curs = conn.cursor()
 
 
execute SELECT
curs.execute('SELECT * FROM tbl')
curs.execute('SELECT * FROM tbl')
curs.execute('SELECT * FROM tbl')
curs.execute('SELECT * FROM tbl')
 
 
fetch
curs.fetchone(); curs.fetchall(); curs.fetchmany()
curs.fetchone(); curs.fetchall(); curs.fetchmany()
curs.fetchone(); curs.fetchall(); curs.fetchmany()
curs.fetchone(); curs.fetchall(); curs.fetchmany(); for r in curs
 
 
use bind variables
curs.execute('SELECT * FROM tbl WHERE col = %(varnm)s', {'varnm':22})
curs.execute('SELECT * FROM tbl WHERE col = ?', [22])
curs.execute('SELECT * FROM tbl WHERE col = %s', [22])
curs.execute('SELECT * FROM tbl WHERE col = :varnm', {'varnm':22})
 
curs.execute('SELECT * FROM tbl WHERE col = ?', (22,))
commit
conn.commit() (required)
conn.commit() (required)
conn.commit() (required)
conn.commit() (required)
 
 


 

Подключение к MySQL


import mysql.connector
from mysql.connector import Error

def connect():
    """ Connect to MySQL database """
    try:
        conn = mysql.connector.connect(host='192.168.0.1',
                                       database='my_db',
                                       user='angor',
                                       password='my_pwd')
        if conn.is_connected():
            print('Connected to MySQL database')

    except Error as e:
        print(e)

    finally:
        conn.close()

if __name__ == '__main__':
    connect()


суббота, 6 сентября 2014 г.

Установка некоторых пакетов python на arch linux

$ sudo pip install ipython

[angor@omega ~]$ ipython
Python 3.4.1 (default, May 19 2014, 17:23:49)
Type "copyright", "credits" or "license" for more information.

IPython 2.2.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]:



$ sudo pip install numpy

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>>



$ sudo pip install matplotlib

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>>



$ sudo pacman -S core/gcc-fortran
$ sudo pip install scipy


или
$ sudo pacman -S scipy

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import scipy
>>>



$ sudo pacman -S extra/python-pyqt5

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import PyQt5
>>>


$ sudo pacman -S python-opengl

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from OpenGL.GL import *
>>> from OpenGL.GLU import *
>>> from OpenGL.GLUT import *
>>>


$ sudo pip install django

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>>


$ sudo pip install pyramid

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyramid
>>>


$ sudo pip install tornado

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tornado
>>>


$ sudo pacman -S python-sip


[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sip
>>>



$ sudo pip install pillow

[angor@omega ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import PIL
>>>


Есть такая книга:
http://flaskbook.com/

Чтобы выполнить примеры из неё, необходимо установить следующие пакеты:

sudo pip install flask flask-script flask-bootstrap flask-moment flask-wtf flask-sqlalchemy flask-migrate flask-mail flask-login forgerypy flask-pagedown markdown bleach flask-httpauth httpie coverage selenium gunicorn







Установка пакета pygame на arch linux

1. Загружаем tarball python-pygame-hg.tar.gz с сайта:

https://aur.archlinux.org/packages/python-pygame-hg/ 

2. Распакуем архив в текущую папку:

tar -xvf  python-pygame-hg.tar.gz 

или в другую папку:
tar -C /myfolder -xvf  python-pygame-hg.tar.gz

3. Перейдем в каталог:

cd  python-pygame-hg

4. Смотрим зависимости:

$ more .AURINFO
pkgbase = python-pygame-hg
        pkgdesc = Python game library
        pkgver = r3349.823708f24a3a
        pkgrel = 1
        url = http://pygame.org/
        arch = i686
        arch = x86_64
        license = LGPL
        makedepends = mercurial
        makedepends = python-setuptools
        depends = python
        depends = libjpeg-turbo
        depends = sdl_ttf
        depends = sdl_image
        depends = sdl_mixer
        depends = portmidi
        provides = python3-pygame
        provides = python3-pygame-svn
        conflicts = python3-pygame
        conflicts = python3-pygame-svn
        replaces = python3-pygame-svn
        source = python-pygame-hg::hg+https://bitbucket.org/pygame/pygame

pkgname = python-pygame-hg

$
 
$ more PKGBUILD
# Maintainer: speps

pkgname=python-pygame-hg
pkgver=r3349.823708f24a3a
pkgrel=1
pkgdesc="Python game library"
arch=(i686 x86_64)
url="http://pygame.org/"
license=('LGPL')
depends=('python' 'libjpeg-turbo' 'sdl_ttf'
         'sdl_image' 'sdl_mixer' 'portmidi')
makedepends=('mercurial' 'python-setuptools')
provides=('python3-pygame' 'python3-pygame-svn')
conflicts=('python3-pygame' 'python3-pygame-svn')
replaces=('python3-pygame-svn')
source=("$pkgname::hg+https://bitbucket.org/pygame/pygame")
md5sums=('SKIP')

pkgver() {
  cd $pkgname
  printf "r%s.%s" "$(hg identify -n)" "$(hg identify -i)"
}

build() {
  cd $pkgname
  python config.py -auto
  python setup.py build
}

package() {
  cd $pkgname
  python setup.py install --prefix=/usr \
                          --root="$pkgdir/"
}

# vim:set ts=2 sw=2 et:
$

5. Устанавливаем зависимые пакеты:
 
$ sudo pacman -S mercurial  python-setuptools  libjpeg-turbo  sdl_ttf  sdl_image  sdl_mixer  portmidi

6. Устанавливаем pygame:

$ makepkg

$ sudo pacman -U *.pkg.tar.xz

7. Проверяем:

$ python
Python 3.4.1 (default, May 19 2014, 17:23:49)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygame
>>>  




вторник, 10 сентября 2013 г.

Логические операции в Python


is - оператор идентичности

is not - оператор неидентичности


a = ["red", 5, None]
b = ["red", 5, None]

здесь a и b ссылаются на разные объекты

print(a is b)

>False


Возвращает True, если ссылка слева указывает на тот же самый объект, что и ссылка справа:

b = a

print(a is b)

>True


Существует понятие пустого объекта None:

a = "Oracle12c"
b = None

print(a is not None)
print(b is None)

>True
>True



Операторы сравнения:

<   -  меньше

<=  -  меньше либо равно

>   -  больше

>=  -  больше либо равно

==  -  равно

!=  -  не равно



a = 2
b = 6

print(a==b)

>False

print(a<b)

>True

print(a<=b, a!=b, a>=b, a>b)

>True True False False




a = ["red", 5, None]
b = ["red", 5, None]

print(a is b)
>False

print(a == b)
>True


Операторы сравнения могут объединяться в цепочки:

a = 9

print(0<=a<=10)

>True

Это удобнее чем выполнять два отдельных оператора сравнения и объединения их результатов через and.


Попытка сравнить несовместимые значения вызывает исключение:

print("oracle" < 5)

Traceback (most recent call last):
  File "None", line 1, in <module>
builtins.TypeError: unorderable types: str() < int()


print("10" < 5)

Traceback (most recent call last):
  File "None", line 1, in <module>
builtins.TypeError: unorderable types: str() < int()


Оператор членства

Для типов данных являющихся последовательностями или коллекциями
таких как:
 строки
 списки
 картежи
мы можем выполнить проверку членства с помощью оператора in
или не членства с помощью оператора not in

f = ("oracle", "java", 3, -9)

print( 3 in f )

>True


print( "python" in f )

>False



phrase = "oracle database administration"

print( "m" in phrase )

>True

print( "base" in phrase )

>True


Логические операторы

and
or
not

Операторы and и or  вычисляются по короткой схеме и возвращают операнд.
Они не возвращают значение типа Boolean, если операнды не являются значениями типа Boolean.

x  or y   -  if x is False, then y, else x
x and y   -  if x is False, then x, else y
not x     -  if x is False, then True, else False


Унарный оператор not оценивает свой операнд в булевом контексте и всегда возвращает значение типа Boolean.

five = 5
two = 2
zero = 0

print(five and two)

>2


print(two and five)

>5


print(five and zero)

>0


Если выражение участвует в логическом контексте, результат оценивается как значение типа Boolean,
поэтому предыдущие выражения могли бы рассматриваться, как имеющие значения True, True и False
в контексте инструкции if.

five = 5
two = 2
zero = 0
nought = 0

print(five or two)

>5

print(two or five)

>2

print(zero or five)

>5

print(zero or nought)

>0

Оператор or напоминает оператор and  -  здесь в булевом контексте были бы получены значения
True, True, True и False.

print(not(zero or nought))

>True

print(not two)

>False




воскресенье, 11 августа 2013 г.

Дополнительные наборы модулей (библиотек) языка программирования Python

IPython - интерактивная оболочка для языка программирования Python, которая предоставляет расширенную интроспекцию,
дополнительный командный синтаксис, подсветку кода и автоматическое дополнение. Является компонентом пакета программ SciPy.


NumPy - это расширение языка Python, добавляющее поддержку больших многомерных массивов и матриц,
вместе с большой библиотекой высокоуровневых математических функций для операций с этими массивами.
Предшественник NumPy, Numeric, был изначально создан Jim Hugunin.



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


Matplotlib - библиотека на языке программирования Python для визуализации данных двумерной (2D) графикой
(3D графика также поддерживается). 
Matplotlib написан и поддерживался в основном Джоном Хантером (англ. John Hunter)
и распространяется на условиях BSD-подобной лицензии.


Pygame - набор модулей (библиотек) языка программирования Python,
предназначенный для написания компьютерных игр и мультимедиа-приложений.
Pygame базируется на мультимедийной библиотеке SDL.
Изначально Pygame был написан Питом Шиннерсом (Pete Shinners).
Начиная примерно с 2004/2005 года поддерживается и развивается сообществом свободного программного обеспечения.


PyOpenGL - библиотека, позволяющим в программах на языке Python легко работать с
функциями OpenGL, GLU и GLUT, а также с рядом расширений OpenGL.


PyQt - набор «привязок» графического фреймворка Qt для языка программирования Python, выполненный в виде расширения Python.



SIP - это инструмент для автоматической генерации Python-привязок к C и C++ библиотекам.
Первоначально SIP был разработан в 1998 году для PyQt — Python-привязки для инструментария виджетов Qt,
но подходит и для создания привязок к любым другим C или C++ библиотекам.
SIP берёт набор инструкций (.sip файлы), описывающих API и генерирует требуемый C++ код.
Потом он компилируется и на выходе получается модуль Python. Файлы .sip — файлы заголовков класса,
у которых кое-что убрано (потому что SIP не содержит полноценный C++-парсер) и кое-что добавлено
(поскольку C++ не несет достаточной информации о работе API).


Python Imaging Library (сокращенно PIL) — библиотека языка Python, предназначенная для работы с растровой графикой.


Django — свободный фреймворк для веб-приложений на языке Python, использующий шаблон проектирования MVC.
Проект поддерживается организацией Django Software Foundation.


Tornado - расширяемый, не блокирующий веб-сервер и фреймворк, написанный на Python.
Он создан для использования в проекте FriendFeed.
Компания была приобретена Facebook в 2009 году и после этого были открыты исходные коды Tornado.
Tornado был создан для обеспечения высокой производительности и является одним из веб-серверов,
способных выдержать проблему 10000 соединений.
Следует понимать, что при сравнении производительности речь идет о т. н. «легких» запросах.
Ибо длительная обработка запроса (например, по причине взаимодействия с сервером баз данных),
сводит преимущества Торнадо на нет.


Pylons — программный каркас для разработки веб-приложений (web application framework) с открытым исходным кодом,
написанный на языке Python. В нём широко используется стандарт WSGI, что способствует эффективности повторного
использования кода и модульности.
В настоящее время развитие Pylons завершено на версии 1.0, а дальнейшего развития (помимо исправления ошибок) не планируется.
В качестве основы для следующего поколения программного каркаса проекта Pylons взят программный каркас repoze.bfg,
получивший в рамках проекта Pylons новое имя — Pyramid. Само название Pylons становится отныне зонтичным брендом.


Pyramid — программный каркас (фреймворк) для разработки веб-приложений
с открытым исходным кодом, написанный на языке Python в рамках проекта Pylons.
На создание Pyramid оказали влияние такие фреймворки, как Zope, Pylons и Django.
Код Pyramid разрабатывался в проекте repoze.bfg, а название поменялось в результате слияния проектов BFG и Pylons.




Комплексные числа в Python

 Тип данных complex относится к категории неизменяемых и хранит пару значений типа float,
одно из которых представляет действительную часть комплексного числа, а другое - мнимую.

Литералы комплексных  чисел записываются как действительная и мнимая части,
объединенные знаком "+" или "-", а за мнимой частью следует символ j.

3.5+2j

0.5j  - если действительная часть равна 0, ее можно вообще опустить.

4+0j

-1-3.7j

 Отдельные части комплексного числа доступны в виде атрибутов real и imag:

>>> z = -89.5+2.125j

>>> z.real, z.imag
(-89.5, 2.125)


За исключением //, %, divmod и версии pow() с тремя аргументами все остальные арифметические операторы и функции,
которые используются для работы с целыми числами, также могут использоваться и для работы с комплексными числами.

Значения типа complex имеют метод:

conjugate()

который изменяет знак мнимой части.


>>> z = -89.5+2.125j

>>> z.conjugate()
(-89.5-2.125j)


>>> 3-4j.conjugate()
(3+4j)



>>> 4j.real
0.0

>>> 4j.imag
4.0

>>> 4j+3+2j
(3+6j)


Тип данных complex может вызываться как функция complex()

без аргументов она вернет:

>>> complex()
0j

с аргументами типа complex она вернет копию аргумента:

>>> complex(9+3j)
(9+3j)

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

>>> complex(0)
0j

>>> complex(1)
(1+0j)

>>> complex(0,1)
1j

При использовании для преобразования функция complex() принимает:
либо единственный строковый аргумент
либо одно или два значения типа float

Если ей передается единственное значение типа float, возвращается комплексное число с мнимой частью равной 0j.


Функции в модуле math не работают с комплексными числами.

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

cmath.phase()
cmath.polar()
cmath.rect()

а также константы:

cmath.pi
cmath.e

которые хранят те же самые значения типа float, что и родственные им константы в модуле math.

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



>>> "{0.real:.3f}{0.imag:+.3f}j".format(4.75917+1.2042j)
'4.759+1.204j'

>>> "{0.real:.3f}{0.imag:+.3f}j".format(4.75917-1.2042j)
'4.759-1.204j'


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




Спецификаторы формата для чисел с плавающей точкой Python

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

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

 В самом конце мы можем указать символ типа:

e  - для вывода числа в экспоненциальной форме, с символом "e" в нижнем регистре.

E  - для вывода числа в экспоненциальной форме, с символом "E" в верхнем регистре.

f  - для вывода числа в стандартной форме

g  - для вывода числа в общей форме, т.е. для небольших чисел действует как символ "f"
      а для очень больших чисел как символ "e".

G  - тоже самое как символ "g", только используется формат  "f" или "E".


Кроме того, допускается использовать символ %, при использовании которого выводимое число умножается на 100
и для вывода применяется формат "f" с добавлением символа "%" в конце числа.


Примеры:

Установим минимальную ширину поля вывода 12 символов и 2 знака после дестичной точки.

import math

s = (10**3) * math.pi
print("[{0:12.2e}]  [{0:12.2E}]   [{0:12.2f}]   [{0:12.2g}]   [{0:12.2G}]  [{0:12.2%}]".format(s))

>  [    3.14e+03]  [    3.14E+03]   [     3141.59]   [     3.1e+03]   [     3.1E+03]  [  314159.27%]


              
Добавим вывод символа-заполнителя (при этом символ выравнивания указывать обязательно).

import math

s = (10**3) * math.pi
print("[{0:*>12.2e}]  [{0:->12.2E}]   [{0:#>12.2f}]   [{0:.>12.2g}]   [{0:$>12.2G}]  [{0:&>12.2%}]".format(s))

> [****3.14e+03]  [----3.14E+03]   [#####3141.59]   [.....3.1e+03]   [$$$$$3.1E+03]  [&&314159.27%]



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

import math

s = (10**3) * math.pi
print("[{0:*>+12.2e}]  [{0:->+12.2E}]   [{0:#>+12.2f}]   [{0:.>+12.2g}]   [{0:$>+12.2G}]  [{0:&>+12.2%}]".format(s))

> [***+3.14e+03]  [---+3.14E+03]   [####+3141.59]   [....+3.1e+03]   [$$$$+3.1E+03]  [&+314159.27%]


суббота, 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))

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


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

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




суббота, 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)])))