python数据库开发_Python-数据库开发

1 classConnection(object):2 """

3 Representation of a socket with a mysql server.4

5 The proper way to get an instance of this class is to call6 connect().7

8 Establish a connection to the MySQL database. Accepts several9 arguments:10

11 :param host: Host where the database server is located12 :param user: Username to log in as13 :param password: Password to use.14 :param database: Database to use, None to not use a particular one.15 :param port: MySQL port to use, default is usually OK. (default: 3306)16 :param bind_address: When the client has multiple network interfaces, specify17 the interface from which to connect to the host. Argument can be18 a hostname or an IP address.19 :param unix_socket: Optionally, you can use a unix socket rather than TCP/IP.20 :param read_timeout: The timeout for reading from the connection in seconds (default: None - no timeout)21 :param write_timeout: The timeout for writing to the connection in seconds (default: None - no timeout)22 :param charset: Charset you want to use.23 :param sql_mode: Default SQL_MODE to use.24 :param read_default_file:25 Specifies my.cnf file to read these parameters from under the [client] section.26 :param conv:27 Conversion dictionary to use instead of the default one.28 This is used to provide custom marshalling and unmarshaling of types.29 See converters.30 :param use_unicode:31 Whether or not to default to unicode strings.32 This option defaults to true for Py3k.33 :param client_flag: Custom flags to send to MySQL. Find potential values in constants.CLIENT.34 :param cursorclass: Custom cursor class to use.35 :param init_command: Initial SQL statement to run when connection is established.36 :param connect_timeout: Timeout before throwing an exception when connecting.37 (default: 10, min: 1, max: 31536000)38 :param ssl:39 A dict of arguments similar to mysql_ssl_set()'s parameters.40 For now the capath and cipher arguments are not supported.41 :param read_default_group: Group to read from in the configuration file.42 :param compress: Not supported43 :param named_pipe: Not supported44 :param autocommit: Autocommit mode. None means use server default. (default: False)45 :param local_infile: Boolean to enable the use of LOAD DATA LOCAL command. (default: False)46 :param max_allowed_packet: Max size of packet sent to server in bytes. (default: 16MB)47 Only used to limit size of "LOAD LOCAL INFILE" data packet smaller than default (16KB).48 :param defer_connect: Don't explicitly connect on contruction - wait for connect call.49 (default: False)50 :param auth_plugin_map: A dict of plugin names to a class that processes that plugin.51 The class will take the Connection object as the argument to the constructor.52 The class needs an authenticate method taking an authentication packet as53 an argument. For the dialog plugin, a prompt(echo, prompt) method can be used54 (if no authenticate method) for returning a string from the user. (experimental)55 :param server_public_key: SHA256 authenticaiton plugin public key value. (default: None)56 :param db: Alias for database. (for compatibility to MySQLdb)57 :param passwd: Alias for password. (for compatibility to MySQLdb)58 :param binary_prefix: Add _binary prefix on bytes and bytearray. (default: False)59

60 See `Connection `_ in the61 specification.62 """

63

64 _sock =None65 _auth_plugin_name = ''

66 _closed =False67 _secure =False68

69 def __init__(self, host=None, user=None, password="",70 database=None, port=0, unix_socket=None,71 charset='', sql_mode=None,72 read_default_file=None, conv=None, use_unicode=None,73 client_flag=0, cursorclass=Cursor, init_command=None,74 connect_timeout=10, ssl=None, read_default_group=None,75 compress=None, named_pipe=None,76 autocommit=False, db=None, passwd=None, local_infile=False,77 max_allowed_packet=16*1024*1024, defer_connect=False,78 auth_plugin_map=None, read_timeout=None, write_timeout=None,79 bind_address=None, binary_prefix=False, program_name=None,80 server_public_key=None):81 if use_unicode is None and sys.version_info[0] > 2:82 use_unicode =True83

84 if db is not None and database isNone:85 database =db86 if passwd is not None and notpassword:87 password =passwd88

89 if compress ornamed_pipe:90 raise NotImplementedError("compress and named_pipe arguments are not supported")91

92 self._local_infile =bool(local_infile)93 ifself._local_infile:94 client_flag |=CLIENT.LOCAL_FILES95

96 if read_default_group and notread_default_file:97 if sys.platform.startswith("win"):98 read_default_file = "c:\\my.ini"

99 else:100 read_default_file = "/etc/my.cnf"

101

102 ifread_default_file:103 if notread_default_group:104 read_default_group = "client"

105

106 cfg =Parser()107 cfg.read(os.path.expanduser(read_default_file))108

109 def_config(key, arg):110 ifarg:111 returnarg112 try:113 returncfg.get(read_default_group, key)114 exceptException:115 returnarg116

117 user = _config("user", user)118 password = _config("password", password)119 host = _config("host", host)120 database = _config("database", database)121 unix_socket = _config("socket", unix_socket)122 port = int(_config("port", port))123 bind_address = _config("bind-address", bind_address)124 charset = _config("default-character-set", charset)125 if notssl:126 ssl ={}127 ifisinstance(ssl, dict):128 for key in ["ca", "capath", "cert", "key", "cipher"]:129 value = _config("ssl-" +key, ssl.get(key))130 ifvalue:131 ssl[key] =value132

133 self.ssl =False134 ifssl:135 if notSSL_ENABLED:136 raise NotImplementedError("ssl module not found")137 self.ssl =True138 client_flag |=CLIENT.SSL139 self.ctx =self._create_ssl_ctx(ssl)140

141 self.host = host or "localhost"

142 self.port = port or 3306

143 self.user = user orDEFAULT_USER144 self.password = password or b""

145 ifisinstance(self.password, text_type):146 self.password = self.password.encode('latin1')147 self.db =database148 self.unix_socket =unix_socket149 self.bind_address =bind_address150 if not (0 < connect_timeout <= 31536000):151 raise ValueError("connect_timeout should be >0 and <=31536000")152 self.connect_timeout = connect_timeout orNone153 if read_timeout is not None and read_timeout <=0:154 raise ValueError("read_timeout should be >= 0")155 self._read_timeout =read_timeout156 if write_timeout is not None and write_timeout <=0:157 raise ValueError("write_timeout should be >= 0")158 self._write_timeout =write_timeout159 ifcharset:160 self.charset =charset161 self.use_unicode =True162 else:163 self.charset =DEFAULT_CHARSET164 self.use_unicode =False165

166 if use_unicode is notNone:167 self.use_unicode =use_unicode168

169 self.encoding =charset_by_name(self.charset).encoding170

171 client_flag |=CLIENT.CAPABILITIES172 ifself.db:173 client_flag |=CLIENT.CONNECT_WITH_DB174

175 self.client_flag =client_flag176

177 self.cursorclass =cursorclass178

179 self._result =None180 self._affected_rows =0181 self.host_info = "Not connected"

182

183 #: specified autocommit mode. None means use server default.

184 self.autocommit_mode =autocommit185

186 if conv isNone:187 conv =converters.conversions188

189 #Need for MySQLdb compatibility.

190 self.encoders = dict([(k, v) for (k, v) in conv.items() if type(k) is notint])191 self.decoders = dict([(k, v) for (k, v) in conv.items() if type(k) isint])192 self.sql_mode =sql_mode193 self.init_command =init_command194 self.max_allowed_packet =max_allowed_packet195 self._auth_plugin_map = auth_plugin_map or{}196 self._binary_prefix =binary_prefix197 self.server_public_key =server_public_key198

199 self._connect_attrs ={200 '_client_name': 'pymysql',201 '_pid': str(os.getpid()),202 '_client_version': VERSION_STRING,203 }204 ifprogram_name:205 self._connect_attrs["program_name"] =program_name206 elifsys.argv:207 self._connect_attrs["program_name"] =sys.argv[0]208

209 ifdefer_connect:210 self._sock =None211 else:212 self.connect()213

214 def_create_ssl_ctx(self, sslp):215 ifisinstance(sslp, ssl.SSLContext):216 returnsslp217 ca = sslp.get('ca')218 capath = sslp.get('capath')219 hasnoca = ca is None and capath isNone220 ctx = ssl.create_default_context(cafile=ca, capath=capath)221 ctx.check_hostname = not hasnoca and sslp.get('check_hostname', True)222 ctx.verify_mode = ssl.CERT_NONE if hasnoca elsessl.CERT_REQUIRED223 if 'cert' insslp:224 ctx.load_cert_chain(sslp['cert'], keyfile=sslp.get('key'))225 if 'cipher' insslp:226 ctx.set_ciphers(sslp['cipher'])227 ctx.options |=ssl.OP_NO_SSLv2228 ctx.options |=ssl.OP_NO_SSLv3229 returnctx230

231 defclose(self):232 """

233 Send the quit message and close the socket.234

235 See `Connection.close() `_236 in the specification.237

238 :raise Error: If the connection is already closed.239 """

240 ifself._closed:241 raise err.Error("Already closed")242 self._closed =True243 if self._sock isNone:244 return

245 send_data = struct.pack('

250 finally:251 self._force_close()252

253 @property254 defopen(self):255 """Return True if the connection is open"""

256 return self._sock is notNone257

258 def_force_close(self):259 """Close connection without QUIT message"""

260 ifself._sock:261 try:262 self._sock.close()263 except: #noqa

264 pass

265 self._sock =None266 self._rfile =None267

268 __del__ =_force_close269

270 defautocommit(self, value):271 self.autocommit_mode =bool(value)272 current =self.get_autocommit()273 if value !=current:274 self._send_autocommit_mode()275

276 defget_autocommit(self):277 return bool(self.server_status &

278 SERVER_STATUS.SERVER_STATUS_AUTOCOMMIT)279

280 def_read_ok_packet(self):281 pkt =self._read_packet()282 if notpkt.is_ok_packet():283 raise err.OperationalError(2014, "Command Out of Sync")284 ok =OKPacketWrapper(pkt)285 self.server_status =ok.server_status286 returnok287

288 def_send_autocommit_mode(self):289 """Set whether or not to commit after every execute()"""

290 self._execute_command(COMMAND.COM_QUERY, "SET AUTOCOMMIT = %s" %

291 self.escape(self.autocommit_mode))292 self._read_ok_packet()293

294 defbegin(self):295 """Begin transaction."""

296 self._execute_command(COMMAND.COM_QUERY, "BEGIN")297 self._read_ok_packet()298

299 defcommit(self):300 """

301 Commit changes to stable storage.302

303 See `Connection.commit() `_304 in the specification.305 """

306 self._execute_command(COMMAND.COM_QUERY, "COMMIT")307 self._read_ok_packet()308

309 defrollback(self):310 """

311 Roll back the current transaction.312

313 See `Connection.rollback() `_314 in the specification.315 """

316 self._execute_command(COMMAND.COM_QUERY, "ROLLBACK")317 self._read_ok_packet()318

319 defshow_warnings(self):320 """Send the "SHOW WARNINGS" SQL command."""

321 self._execute_command(COMMAND.COM_QUERY, "SHOW WARNINGS")322 result =MySQLResult(self)323 result.read()324 returnresult.rows325

326 defselect_db(self, db):327 """

328 Set current db.329

330 :param db: The name of the db.331 """

332 self._execute_command(COMMAND.COM_INIT_DB, db)333 self._read_ok_packet()334

335 def escape(self, obj, mapping=None):336 """Escape whatever value you pass to it.337

338 Non-standard, for internal use; do not use this in your applications.339 """

340 ifisinstance(obj, str_type):341 return "'" + self.escape_string(obj) + "'"

342 ifisinstance(obj, (bytes, bytearray)):343 ret =self._quote_bytes(obj)344 ifself._binary_prefix:345 ret = "_binary" +ret346 returnret347 return converters.escape_item(obj, self.charset, mapping=mapping)348

349 defliteral(self, obj):350 """Alias for escape()351

352 Non-standard, for internal use; do not use this in your applications.353 """

354 returnself.escape(obj, self.encoders)355

356 defescape_string(self, s):357 if (self.server_status &

358 SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES):359 return s.replace("'", "''")360 returnconverters.escape_string(s)361

362 def_quote_bytes(self, s):363 if (self.server_status &

364 SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES):365 return "'%s'" % (_fast_surrogateescape(s.replace(b"'", b"''")),)366 returnconverters.escape_bytes(s)367

368 def cursor(self, cursor=None):369 """

370 Create a new cursor to execute queries with.371

372 :param cursor: The type of cursor to create; one of :py:class:`Cursor`,373 :py:class:`SSCursor`, :py:class:`DictCursor`, or :py:class:`SSDictCursor`.374 None means use Cursor.375 """

376 ifcursor:377 returncursor(self)378 returnself.cursorclass(self)379

380 def __enter__(self):381 """Context manager that returns a Cursor"""

382 returnself.cursor()383

384 def __exit__(self, exc, value, traceback):385 """On successful exit, commit. On exception, rollback"""

386 ifexc:387 self.rollback()388 else:389 self.commit()390

391 #The following methods are INTERNAL USE ONLY (called from Cursor)

392 def query(self, sql, unbuffered=False):393 #if DEBUG:

394 #print("DEBUG: sending query:", sql)

395 if isinstance(sql, text_type) and not (JYTHON orIRONPYTHON):396 ifPY2:397 sql =sql.encode(self.encoding)398 else:399 sql = sql.encode(self.encoding, 'surrogateescape')400 self._execute_command(COMMAND.COM_QUERY, sql)401 self._affected_rows = self._read_query_result(unbuffered=unbuffered)402 returnself._affected_rows403

404 def next_result(self, unbuffered=False):405 self._affected_rows = self._read_query_result(unbuffered=unbuffered)406 returnself._affected_rows407

408 defaffected_rows(self):409 returnself._affected_rows410

411 defkill(self, thread_id):412 arg = struct.pack('

416 def ping(self, reconnect=True):417 """

418 Check if the server is alive.419

420 :param reconnect: If the connection is closed, reconnect.421 :raise Error: If the connection is closed and reconnect=False.422 """

423 if self._sock isNone:424 ifreconnect:425 self.connect()426 reconnect =False427 else:428 raise err.Error("Already closed")429 try:430 self._execute_command(COMMAND.COM_PING, "")431 self._read_ok_packet()432 exceptException:433 ifreconnect:434 self.connect()435 self.ping(False)436 else:437 raise

438

439 defset_charset(self, charset):440 #Make sure charset is supported.

441 encoding =charset_by_name(charset).encoding442

443 self._execute_command(COMMAND.COM_QUERY, "SET NAMES %s" %self.escape(charset))444 self._read_packet()445 self.charset =charset446 self.encoding =encoding447

448 def connect(self, sock=None):449 self._closed =False450 try:451 if sock isNone:452 ifself.unix_socket:453 sock =socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)454 sock.settimeout(self.connect_timeout)455 sock.connect(self.unix_socket)456 self.host_info = "Localhost via UNIX socket"

457 self._secure =True458 if DEBUG: print('connected using unix_socket')459 else:460 kwargs ={}461 if self.bind_address is notNone:462 kwargs['source_address'] =(self.bind_address, 0)463 whileTrue:464 try:465 sock =socket.create_connection(466 (self.host, self.port), self.connect_timeout,467 **kwargs)468 break

469 except(OSError, IOError) as e:470 if e.errno ==errno.EINTR:471 continue

472 raise

473 self.host_info = "socket %s:%d" %(self.host, self.port)474 if DEBUG: print('connected using socket')475 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)476 sock.settimeout(None)477 sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)478 self._sock =sock479 self._rfile = _makefile(sock, 'rb')480 self._next_seq_id =0481

482 self._get_server_information()483 self._request_authentication()484

485 if self.sql_mode is notNone:486 c =self.cursor()487 c.execute("SET sql_mode=%s", (self.sql_mode,))488

489 if self.init_command is notNone:490 c =self.cursor()491 c.execute(self.init_command)492 c.close()493 self.commit()494

495 if self.autocommit_mode is notNone:496 self.autocommit(self.autocommit_mode)497 exceptBaseException as e:498 self._rfile =None499 if sock is notNone:500 try:501 sock.close()502 except: #noqa

503 pass

504

505 ifisinstance(e, (OSError, IOError, socket.error)):506 exc =err.OperationalError(507 2003,508 "Can't connect to MySQL server on %r (%s)" %(509 self.host, e))510 #Keep original exception and traceback to investigate error.

511 exc.original_exception =e512 exc.traceback =traceback.format_exc()513 if DEBUG: print(exc.traceback)514 raiseexc515

516 #If e is neither DatabaseError or IOError, It's a bug.

517 #But raising AssertionError hides original error.

518 #So just reraise it.

519 raise

520

521 defwrite_packet(self, payload):522 """Writes an entire "mysql packet" in its entirety to the network523 addings its length and sequence number.524 """

525 #Internal note: when you build packet manualy and calls _write_bytes()

526 #directly, you should set self._next_seq_id properly.

527 data = pack_int24(len(payload)) + int2byte(self._next_seq_id) +payload528 ifDEBUG: dump_packet(data)529 self._write_bytes(data)530 self._next_seq_id = (self._next_seq_id + 1) % 256

531

532 def _read_packet(self, packet_type=MysqlPacket):533 """Read an entire "mysql packet" in its entirety from the network534 and return a MysqlPacket type that represents the results.535

536 :raise OperationalError: If the connection to the MySQL server is lost.537 :raise InternalError: If the packet sequence number is wrong.538 """

539 buff = b''

540 whileTrue:541 packet_header = self._read_bytes(4)542 #if DEBUG: dump_packet(packet_header)

543

544 btrl, btrh, packet_number = struct.unpack('

550 raiseerr.OperationalError(551 CR.CR_SERVER_LOST,552 "Lost connection to MySQL server during query")553 raiseerr.InternalError(554 "Packet sequence number wrong - got %d expected %d"

555 %(packet_number, self._next_seq_id))556 self._next_seq_id = (self._next_seq_id + 1) % 256

557

558 recv_data =self._read_bytes(bytes_to_read)559 ifDEBUG: dump_packet(recv_data)560 buff +=recv_data561 #https://dev.mysql.com/doc/internals/en/sending-more-than-16mbyte.html

562 if bytes_to_read == 0xffffff:563 continue

564 if bytes_to_read

&CLIENT.SSL:681

&CLIENT.SSL:706

&CLIENT.PLUGIN_AUTH_LENENC_CLIENT_DATA:713&CLIENT.SECURE_CONNECTION:715

&CLIENT.CONNECT_WITH_DB:720

&CLIENT.PLUGIN_AUTH:725

&CLIENT.CONNECT_ATTRS:728

&

&

&

<<

&

<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值