Hướng dẫn is mysql and pymysql the same? - mysql và pymysql có giống nhau không?

MySQLDB là một trình bao bọc python mỏng xung quanh mô -đun C, thực hiện API cho cơ sở dữ liệu MySQL.

Có phiên bản MySQLDB1 của Wrapper được sử dụng cách đây một thời gian và bây giờ nó được coi là một di sản. Khi MySQLDB1 bắt đầu phát triển thành MySQLDB2 với các sửa lỗi và hỗ trợ Python3, một MySQLDB1 đã bị chia tay và đây là cách MySQLClient xuất hiện, với Bugfixes và Python3 hỗ trợ. Tóm lại, vì vậy bây giờ chúng tôi có MySQLDB2 chưa sẵn sàng để sử dụng sản xuất, MySQLDB1 làm trình điều khiển lỗi thời và cộng đồng đã hỗ trợ mysqlclient với các sửa lỗi lỗi và hỗ trợ Python3.

Bây giờ, để giải quyết mớ hỗn độn đó, MySQL cung cấp phiên bản bộ điều hợp MySQL của riêng họ - Trình kết nối MySQL, một mô -đun Python toàn bộ sử dụng API MYSQL mà không phụ thuộc vào mô -đun C và chỉ được sử dụng các mô -đun Python tiêu chuẩn.no C modules dependencies and only standard python modules used.

Vì vậy, bây giờ câu hỏi được đưa ra: mysqlclient vs kết nối MySQL.

Đối với tôi, tôi sẽ đi với thư viện được hỗ trợ chính thức, tuy nhiên mysqlclient cũng sẽ là một lựa chọn tốt. Cả hai đều đang được cập nhật tích cực với các bản sửa lỗi và các tính năng mới mà bạn có thể thấy bằng cách hoạt động trong những ngày cuối cùng.

Lưu ý: Tôi không có nhiều kinh nghiệm với họ, vì vậy có thể có trường hợp khi người này hoặc người khác không phù hợp với nhu cầu của bạn. Cả hai thư viện đều tuân theo tiêu chuẩn PEP-249, điều đó có nghĩa là bạn sẽ ổn với ít nhất chức năng cơ sở ở mọi nơi.

Cài đặt và phụ thuộc

  • mysqlclient

Là một cái nĩa của trình bao tải C, nó yêu cầu các mô-đun C phải hoạt động với MySQL, bổ sung các tệp tiêu đề Python để xây dựng các tiện ích mở rộng này (đọc Python-dev). Cài đặt phụ thuộc vào hệ thống bạn sử dụng, chỉ cần đảm bảo bạn biết tên gói và có thể cài đặt chúng.

  • Tài liệu chính của đầu nối MySQL khá rõ ràng, tuy nhiên bạn nên biết về sự phụ thuộc của ProtObuf C ++ (đối với các phiên bản kết nối MySQL> = 2.2.3).

Nội dung

  • Đánh giá 1pymysql PyMySQL Evaluation
    • 1.1Rationale Rationale
    • 1.2DVERS đang được xem xét Drivers Under Consideration
      • 1.2.1MySQL-Python MySQL-Python
      • 1.2.2mysqlclient mysqlclient
      • 1.2.3OurSQL OurSQL
      • 1.2.4MySQL-Connector-Python MySQL-Connector-Python
      • 1.2.5PyMySQL PyMySQL
      • 1.2.6Mysql trình điều khiển DB MySQL DB Drivers Comparison
    • Đánh giá mã 1.3PyMysQL PyMySQL Code Review
      • 1.3.1 Phong cách mã hóa / PEP8 Coding Style / Pep8
      • 1.3.2 Phạm vi bảo hiểm Test Coverage
      • 1.3.3 Tài liệu thư viện Library Documentation
      • 1.3.44charchecture và hiệu suất Architecture and Performance
      • 1.3.5 Tài liệu History Documentation
      • 1.3.6 Sự tham gia của cộng đồng Community Involvement
      • 1.3.7APPENDIX A - Bài kiểm tra hiệu suất Appendix A - Performance Tests

Đánh giá PYMYSQL

Trang này sẽ nắm bắt các vấn đề liên quan đến OpenStack chuyển sang trình điều khiển PYMYSQL cho truy cập DBAPI của MySQL/Mariadb.

Cơ sở lý luận

Mặc dù trình điều khiển MySQL-Python là một trình điều khiển rất trưởng thành và ổn định, nhưng nó không cung cấp khả năng tương thích với Python 3 hoặc với sự kiện Eventlet (MySQL-Python có thể được tính phí với Eventlet, nhưng tính năng này bị tắt theo mặc định và bị bỏ lỡ trong tài liệu). Vì vậy, việc sử dụng MySQL-Python của OpenStack, kết hợp với thực tế là sự đồng thời được cung cấp bởi Eventlet, có nghĩa là chúng tôi hiện có quyền truy cập cơ sở dữ liệu được tuần tự hóa hoàn toàn trong một quy trình duy nhất, nghĩa là chỉ có một lệnh cơ sở dữ liệu xảy ra tại một thời điểm trong quá trình Python OpenStack.

Trình điều khiển đang được xem xét

Hai trình điều khiển được biết là cung cấp khả năng tương thích của Eventlet-MonKeypatch là MySQL-Connector và PYMYSQL, vì chúng được viết bằng Python thuần túy. Hai trình điều khiển nổi tiếng khác cho MySQL là MySQL-Python và OurSQL, cả hai đều được viết bằng C và không cung cấp hỗ trợ rõ ràng cho Eventlet hoặc Async. Chúng có thể được xây dựng để hỗ trợ Gevent bằng cách sử dụng một hệ thống gọi là Greenify, nhưng sự trưởng thành và/hoặc Stabiltiy của hệ thống này vẫn chưa được biết.

Một so sánh tại http://www.diamondtin.com/2014/sqlalchemy-gevent-mysql-python-drivers-comparison/ minh họa các số liệu hiệu suất được quan sát với cả bốn trình điều khiển này, với Mysql-python được xây dựng " hệ thống.

Một bản tóm tắt về tình trạng của cả bốn trình điều khiển như sau.

MySQL-Python

MySQL-Python là trình điều khiển Python được sử dụng rộng rãi nhất. Tuy nhiên, nó không hỗ trợ Python 3 và nó không hỗ trợ các hệ thống Async trừ khi được sử dụng trong nhóm luồng. Mặc dù một hệ thống được gọi là Greenify có khả năng giải quyết tình huống thứ hai, giới hạn Python 3 vẫn là một công cụ phá vỡ thỏa thuận-yêu cầu kéo với sự hỗ trợ của Python 3 đã được đề xuất cho MySQL-Python vào tháng 4 năm 2014 và vẫn chưa được hợp nhất.

mysqlclient

Mysqlclient là một cái nĩa của MySQL-Python hoạt động trong Python 3.3. Nó có chức năng đầy đủ và vượt qua tất cả các bài kiểm tra đơn vị SQLalchemy, và cũng được duy trì bởi cùng một người duy trì PYMYSQL.

Của chúng tôi

OurSQL là trình điều khiển MySQL thay thế cũng được viết bằng C. Nó có hiệu suất nhanh và sử dụng mô hình thực thi khác với MySQL-Python, sử dụng các câu lệnh đã chuẩn bị. OurSQL có cổng Python 3 được lưu trữ trên Launchpad nhưng không được tích hợp với chính chúng tôi cũng không được xuất bản trên PYPI. Bởi vì nó được viết bằng C, nó không cung cấp khả năng tương thích với các hệ thống ASYNC bao gồm cả việc khỉ kiểu Eventlet.

Bên cạnh sự hỗ trợ của Python 3 Shaky 3 và thiếu sự hỗ trợ của Eventlet, chúng tôi cũng không được duy trì, chứng kiến ​​sự cam kết chính cuối cùng của nó vào năm 2012-06-05.

MySQL-Connector-Python

MySQL-ConneNector-Python là một trình điều khiển Python Python thuần túy, và hiện được phát hành dưới sự bảo trợ của chính dự án MySQL, thuộc sở hữu của Oracle. MySQL-ConneNector-Python hỗ trợ cả Python 3 cũng như Khỉ chiều Eventlet và được duy trì tốt. Nó được chứng thực bởi Oracle là trình điều khiển được hỗ trợ chính thức của Oracle cho MySQL, vì vậy, đến mức đó, theo hầu hết các cách lựa chọn đầu tiên của OpenStack trong trình điều khiển. Tuy nhiên, Oracle từ chối xuất bản MySQL-ConneNector-Python trên PYPI, điều này rất quan trọng đối với cơ sở hạ tầng OpenStack. Các nỗ lực lặp đi lặp lại để giao tiếp với Oracle để giải quyết vấn đề này đã không đạt được bất kỳ tiến bộ nào. Do đó, vì một lý do đáng tiếc này, MySQL-ConneNector-Python sẽ không có vị trí trong hệ sinh thái OpenStack trừ khi vấn đề này được giải quyết.

PYMYSQL

PYMYSQL là một trình điều khiển Python Python thuần túy, lần đầu tiên được viết là một cổng thô của trình điều khiển MySQL-Python. PYMYSQL đáp ứng tất cả các tiêu chí của OpenStack cho một trình điều khiển: nó là nguồn mở hoàn toàn, được lưu trữ trên GitHub, được phát hành trên PYPI, được duy trì tích cực, được viết bằng Python Pure Python, vì vậy Eventlet-MonKeypatch tương thích và hoàn toàn tương thích với Python 3.

Vì tài liệu này được đặt tên là "Đánh giá PYMYSQL", nên rõ ràng đây là trình điều khiển OpenStack hiện đang nghiêng về; Bởi vì nó là người duy nhất đáp ứng đầy đủ tất cả các tiêu chí, nó rất có thể là "người chiến thắng". Tuy nhiên, nó có một số vấn đề chất lượng mã nhỏ mà hy vọng có thể được giải quyết theo một cách nào đó; Phần dưới đây có tiêu đề "Đánh giá mã PYMYSQL" sẽ tóm tắt trạng thái hiện tại của mã.

So sánh trình điều khiển DB của MySQL

Dự án Pypi đã tổ chức Sự kiện thân thiện Tương thích Python 3 Thời gian đáo hạn và/hoặc ổn định Bình luận
Mysql-python Đúng Một phần Không Đúng Một phần
Không Đúng Một phần Đúng Đúng Một phần
Không Đúng Không Có thể bị khỉ Không Có thể bị khỉ
mysqlclient Không Đúng Đúng Một phần Không
Có thể bị khỉ Đúng Đúng Đúng Một phần Không

Có thể bị khỉ

mysqlclient

Phong cách mã hóa / PEP8

Phong cách mã hóa của PYMYSQL là khá tốt. Phần lớn trong số đó vượt qua tất cả các bài kiểm tra Flake8, tiết kiệm cho vài chục vấn đề về khoảng trắng và một số dòng dài ở đây và trong các mô -đun cốt lõi, và moreso trong các thử nghiệm có vẻ khó khăn hơn một chút so với các mô -đun cốt lõi. Một lần chạy hoàn toàn của Flake8 chỉ tạo ra 128 lỗi và với một lần chạy mặc định của AutopeP8 so với E1, E2, E3, chúng ta có thể sửa tất cả chúng trong một lần vượt qua ngoại trừ 38 cảnh báo dài còn lại. Bố cục mã chủ yếu là thành ngữ và hợp lý.

CodeBase có lẽ là ngắn trên DocStrings. Những phương pháp đó là một phần của DBAPI công khai có tài liệu, nhưng có xu hướng cực kỳ ngắn gọn (ví dụ, DocString cho con trỏ.execute (): "'Thực hiện truy vấn'"). Các phương pháp khác không có xu hướng công khai không có bất kỳ tài liệu nào, nhưng cơ sở mã không khó đọc và mục đích của các phương thức và chức năng là khá dễ nhận ra chỉ bằng tên và triển khai của họ, tuy nhiên những người tìm kiếm tài liệu nội tuyến là Một phương tiện để hiểu một cơ sở mã sẽ thất vọng. Sự khó khăn của các tài liệu API công khai là một vấn đề về việc thiếu tài liệu chung cho PYMYSQL, hãy xem phần "Tài liệu" bên dưới.

Kiểm tra vùng phủ sóng

Phạm vi kiểm tra cho PYMYSQL chắc chắn là thiếu. Từ việc kiểm tra trực quan một mình, rõ ràng là hàng tá các mô -đun thử nghiệm, hầu hết chúng có ít hơn mười thử nghiệm mỗi và các mô -đun là rất ngắn. Đối với một lần chạy thử đầy đủ, chỉ có 126 bài kiểm tra; Tương phản điều này với MySQL-ConneNector-Python có 531 bài kiểm tra.

Ngoài ra, tất cả các thử nghiệm là các thử nghiệm Trip Trip trực tiếp đối với cơ sở dữ liệu thực. Không có bài kiểm tra đơn vị nào không sống dưới bất kỳ hình thức nào, để lại các codepath không dễ dàng thực hiện trên cơ sở dữ liệu MySQL chung trong cái lạnh. Điều này có nghĩa là các tính năng được thiết kế cho các phiên bản cụ thể của MySQL, các kiểu dữ liệu cụ thể, các điều kiện lỗi cụ thể và các loại gói tin nhắn cụ thể không được tạo cho Real chỉ đơn giản là không được kiểm tra.

Việc thiếu các bài kiểm tra là rõ ràng khi chạy với phạm vi bảo hiểm. Bản thân bộ thử nghiệm dường như không có bất kỳ dấu hiệu nào cho thấy nó thường được chạy với phạm vi bảo hiểm, không có chỉ thị trong Tox.ini hoặc tương tự. Với phạm vi bảo hiểm, phạm vi bảo hiểm tổng thể là 85%, nhưng các mô -đun thiếu bảo hiểm nhất cũng là quan trọng nhất đối với chức năng cốt lõi của PYMYSQL, Kết nối.py, Converters.py và con trỏ.py:

Name                                                              Stmts   Miss  Cover
-------------------------------------------------------------------------------------
pymysql/__init__                                                     51      3    94%
pymysql/_compat                                                      14      4    71%
pymysql/_socketio                                                    72     30    58%
pymysql/charset                                                     228      3    99%
pymysql/connections                                                 827    188    77%
pymysql/constants/CLIENT                                             18      0   100%
pymysql/constants/COMMAND                                            32      0   100%
pymysql/constants/ER                                                471      0   100%
pymysql/constants/FIELD_TYPE                                         29      0   100%
pymysql/constants/FLAG                                               15      0   100%
pymysql/constants/SERVER_STATUS                                      10      0   100%
pymysql/constants/__init__                                            0      0   100%
pymysql/converters                                                  148     51    66%
pymysql/cursors                                                     273     37    86%
pymysql/err                                                          40      1    98%
pymysql/tests/__init__                                               14      5    64%
pymysql/tests/base                                                   25      2    92%
pymysql/tests/test_DictCursor                                        73      2    97%
pymysql/tests/test_SSCursor                                          56      6    89%
pymysql/tests/test_basic                                            186      4    98%
pymysql/tests/test_connection                                        57      8    86%
pymysql/tests/test_example                                           17      2    88%
pymysql/tests/test_issues                                           300     48    84%
pymysql/tests/test_load_local                                        39      2    95%
pymysql/tests/test_nextset                                           43      4    91%
pymysql/tests/thirdparty/__init__                                     7      5    29%
pymysql/tests/thirdparty/test_MySQLdb/__init__                        6      2    67%
pymysql/tests/thirdparty/test_MySQLdb/capabilities                  196     23    88%
pymysql/tests/thirdparty/test_MySQLdb/dbapi20                       423    121    71%
pymysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities      73      6    92%
pymysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20          100      2    98%
pymysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard       57      3    95%
pymysql/times                                                        12      0   100%
pymysql/util                                                         14      7    50%
-------------------------------------------------------------------------------------
TOTAL                                                              3926    569    86%

Việc thiếu phạm vi bảo hiểm trong bộ chuyển đổi.py đề cập đến các chức năng liên quan đến việc xử lý các giá trị ràng buộc đến cũng như các giá trị kết quả đi. Dữ liệu chính thoát khỏi các tính năng như thoát khỏi từ điển, bộ, một số đối tượng Unicode và các đối tượng byte cũng như nhiều đường dẫn vào các chức năng xử lý ngày và thời gian không được đề cập.

Trong Connections.py, các tính năng chưa được khám phá bao gồm các tính năng của SSL và rất di sản (ví dụ: phiên bản 3.23) các tính năng MySQL, nhưng cũng có một số tính năng phân tích giao thức.

Trong con trỏ.py, có phạm vi bảo hiểm cho một tính năng liên quan đến hiệu suất phức tạp và chủ yếu không có giấy tờ để viết lại một câu lệnh chèn để có một mệnh đề giá trị mở rộng (_DO_EXECUTE_MANY), tuy nhiên nó không bao gồm trường hợp rất có thể trong đó Đầu vào được đặt thành nhiều khối:

>         for arg in args:
>             v = values % escape(arg, conn)
>             if isinstance(v, text_type):
>                 v = v.encode(encoding)
>             if len(sql) + len(v) + 1 > max_stmt_length:
!                 rows += self.execute(sql)
!                 sql = bytearray(prefix)
>             else:
>                 sql += b','
>             sql += v
>         rows += self.execute(sql)

Phạm vi bảo hiểm còn thiếu nổi bật nhất trong con trỏ.py dường như dành cho hỗ trợ "con trỏ có thể cuộn" của nó.

Ngoài việc thiếu tính đầy đủ trong thử nghiệm, nhiều bài kiểm tra được viết theo kiểu "một thử nghiệm khổng lồ" trong đó hàng chục xác nhận và hành vi cá nhân được gộp vào một trường hợp thử nghiệm lớn (xem Test_Sscursor.py, Test_Basic.py-> Test_Datatypes ví dụ như). Các trường hợp thử nghiệm như thế này rất khó để làm việc khi gỡ lỗi hồi quy cũng như khi các bài kiểm tra cho các tính năng mới cần được thêm vào, và lý tưởng nhất là chúng nên được chia thành các bài kiểm tra tính năng đơn với các đồ đạc phù hợp.

Ngoài ra còn có một bộ gọi là "test_issues", dự định tích lũy các bài kiểm tra chống lại các vấn đề cụ thể đã được báo cáo. Đây không phải là một ý tưởng tồi, mặc dù thật tuyệt khi thấy một nỗ lực được thực hiện để phân loại các thử nghiệm này thành các tính năng thực tế mà chúng đang thử nghiệm, thay vì một danh sách vô nghĩa về số vấn đề, sau đó có thể tạo thành cơ sở cho các bộ mới xung quanh những lĩnh vực chức năng. Các vấn đề được báo cáo nên được sử dụng làm nguồn cảm hứng để cải thiện bộ thử nghiệm, thay vì chỉ là một mục khác được nộp.

Tài liệu thư viện

Vì Python DBAPI đã là API được ghi chép rõ ràng và người dùng PYMYSQL thường đến từ MySQL-Python được ghi lại ở một mức độ nào đó và hợp đồng sử dụng được biết đến Tài liệu toàn diện cụ thể cho thư viện này.

Điều đó đang được nói, PYMYSQL dường như không có bất kỳ tài liệu thư viện thực sự nào. Có một readme về cơ bản đề cập đến PEP-249, một ví dụ trong root cho thấy một kết nối / chuyến đi khứ hồi rất cơ bản, và đó là nó. Để biết bất cứ điều gì về API, các tham số cụ thể, chiến lược tối ưu hóa, hành vi, v.v., người ta phải tắt tài liệu MySQL-Python và giả sử PYMYSQL cũng có cùng tham số hoặc đọc mã nguồn.

PYMYSQL có lẽ đã không có nhiều nhu cầu cấp thiết cho tài liệu thực sự cho đến nay. Tuy nhiên, dựa vào việc trở thành một cảng của Mysql-python nhanh chóng trở thành một thứ không còn có thể dựa vào, vì sự phát triển của Mysql-Python khá bị đình trệ, và PYMYSQL nên khao khát chuyển sang tương lai của MySQL và Python với các tính năng riêng và hành vi cư xử. Cuối cùng, nó sẽ là một ý tưởng tuyệt vời nếu ít nhất nó đã bắt đầu bản dựng Sphinx thô sơ bao gồm AutoDoc cho tài liệu mô -đun mà sau đó có thể được xuất bản lên RTD. Điều này sẽ rất dễ bắt đầu, và một khi có mặt, các phần tài liệu mới có thể được thêm vào lặp đi lặp lại.

Kiến trúc và hiệu suất

Như đã nói trước đây, PYMYSQL có một thực hiện thực sự thực tế và đơn giản. Mã này rất dễ đọc và thật dễ dàng để phân biệt ngay cả các tính năng bất thường như chèn..values ​​viết lại. Theo như thiết kế, có rất nhiều lĩnh vực mà hiệu suất phải chịu một chút ở cấp độ Python; Những khu vực này có thể được cải thiện rất dễ dàng với một chút chú ý.

Khi chúng tôi đang xử lý một trình điều khiển đang giao tiếp với một giao thức cấp thấp trên ổ cắm, điều quan trọng là việc gửi và nhận tin nhắn được thực hiện hiệu quả nhất có thể. Các cơ chế được sử dụng trong PYMYSQL phụ thuộc rất nhiều vào các đối tượng Python tiêu chuẩn, mà không cần sử dụng __Slots__; Điều này có nghĩa là đối với các tin nhắn riêng lẻ trên ổ cắm, chúng tôi đang tạo một đối tượng hạng nặng, gọi phương thức __init __ () của nó và tạo một __dict__ mới mỗi lần; Đối tượng phổ biến nhất, okpacketwrapper (), đã kết thúc một đối tượng mysqlpack (), vì vậy chúng tôi đang thực hiện hai __init __ () s trong trường hợp phổ biến này. OkPacketWrapper cũng thực hiện sơ đồ `__getAttr__` để truy cập thuộc tính proxy từ chính nó đến mysqlpacket nội bộ; Đây là một chế độ hoạt động không hiệu quả trong Python vì điều đó có nghĩa là trước tiên phải xem trước OKPacketWrapper trước khi gọi phương thức `__getAttr __ ()` và thực hiện tra cứu thuộc tính khác. Một nghiên cứu lại của các lớp gói để tạo ra ít đối tượng hơn cho các tin nhắn cũng như sử dụng __Slots__ sẽ được khuyến nghị.

Cũng có ít nhất một số lĩnh vực mà chi phí gọi chức năng cao không cần thiết do tổ chức các cuộc gọi. Ví dụ: khi gọi con trỏ.execute (), đối với các tham số được truyền dưới dạng từ điển theo Python 2K, hàm isinstance () sẽ được gọi trên các đối số đến bốn lần ở mức tối thiểu tiêu chuẩn. Logic bổ sung sau đó sẽ gọi isInstance () trên mọi khóa của từ điển cũng như ít nhất hai lần trên mọi giá trị trong từ điển, để xác định xem giá trị có cần được chuyển đổi thành byte cũng như cho một số logic thoát khỏi cấp cao nhất Séc; Logic thoát ra sau đó đi xa hơn với nhiều kiểm tra hơn cho loại () để khớp với đối tượng với hàm chuyển đổi cuối cùng. Mặc dù dòng chảy của logic này có vẻ hợp lý và đơn giản, nhưng nó không lý tưởng cho thư viện trình điều khiển cơ sở dữ liệu cấp thấp trong đó tốc độ là ưu tiên cao; Các trình bao bọc và bộ xử lý khác nhau có thể dễ dàng được tổ chức lại ở đây để giảm số lượng các cuộc gọi isInstance () và loại () đáng kể, điều này sẽ tiết kiệm rất nhiều cho chi phí gọi chức năng. Có khả năng có nhiều lĩnh vực khác trong cơ sở mã trong đó việc giảm số lượng cuộc gọi tương tự có thể được thực hiện mà không bị gián đoạn quá nhiều.

Trong Phụ lục A, một bộ hiệu suất ngắn được minh họa. Điều này được chạy chống lại PYMYSQL, MySQL-ConneNector-Python và MySQL-Python. Trên thực tế, PYMYSQL thể hiện hành vi gọi cuộc gọi cao nhất, ghi lại 26.851.003 cuộc gọi chức năng so với 11.674.074 của MySQL-Connector cho cùng một hoạt động. Đối với tín dụng của PYMYSQL, bằng cách nào đó, nó hoàn thành thử nghiệm nhanh hơn 25-50% so với MySQL-Connector mặc dù có nhiều hơn gấp đôi số cuộc gọi chức năng; Điều này có thể cho thấy việc sử dụng một cái gì đó rất chậm trong MYSQL-Connector, chẳng hạn như bắt một ngoại lệ trong một vòng lặp chặt chẽ. Tuy nhiên, thanh thực sự mà chúng tôi so sánh là MySQL-Python, được viết bằng C và toàn bộ bài kiểm tra chỉ với 47.503 cuộc gọi chức năng Python; Trong khi PYMYSQL và MySQL-ConneNector-Python cạnh tranh về thời gian trong phạm vi 10-15 giây mà không cần lập hồ sơ, MySQL-Python hoàn thành toàn bộ bài kiểm tra trong ** 1,03 giây **, cải thiện 1000% so với PYMYSQL. Sự khác biệt tốc độ này không phải là lỗi của PYMYSQL, vì Python thuần túy được biết là cực kỳ chậm so với mã C. Tuy nhiên, có rất nhiều chiến thắng dễ dàng trong cơ sở mã của PYMYSQL trong đó số lượng cuộc gọi chức năng có thể được giảm đáng kể để thậm chí còn tốt hơn so với MySQL-ConneNector-Python; Lý tưởng nhất là trình điều khiển sẽ có thể chạy thử nghiệm này có thể chậm hơn 5-6 lần so với MySQL-Python thay vì 10 lần.

Tài liệu lịch sử

PYMYSQL bao gồm một tệp Changelog trong gốc của nó mô tả các sửa lỗi và tính năng của mỗi bản phát hành. Việc xây dựng tệp này chắc chắn nằm trong phong cách "nhanh chóng" được ghi nhận cho tổng thể PYMYSQL và để nó thực sự hữu ích cho phần mềm cấp doanh nghiệp, nó sẽ cần phải hoàn thành chi tiết hơn nhiều. Mỗi sửa lỗi được đề cập chỉ được đề cập đến một cách khó khăn mà không có bất kỳ liên kết nào đến một yêu cầu kéo hoặc báo cáo lỗi. Mặc dù một số có thể được liên kết với một thay đổi cụ thể thông qua công việc thám tử ("con trỏ.fetchall () và. " - Vấn đề là gì?) Và trong nhiều trường hợp không thể (" Hỗ trợ PY3K được cải thiện "). Tệp cũng bao gồm không có ngày nào để người ta phải xem các thẻ GIT để tìm ra phần này (may mắn thay, phát hành dường như được gắn thẻ Git ít nhất). Đối với người dùng đang cố gắng xác định xem các vấn đề cụ thể có được khắc phục hay nếu các hành vi đã thay đổi, tệp này rất khó chịu.

Một danh sách các ngày phát hành minh họa trung bình hai bản phát hành mỗi năm, không bao gồm năm 2012 khi PYMYSQL đang tìm kiếm một người bảo trì mới:

2014-12-02 12:05:10 -0200  (tag: pymysql-0.6.3)
2014-04-21 14:28:47 -0300  (tag: pymysql-0.6.2)
2013-10-11 13:36:56 -0300  (tag: pymysql-0.6.1)
2013-10-04 14:25:14 -0300  (tag: pymysql-0.6)
2011-11-08 10:27:41 -0800  (tag: pymysql-0.5)
2010-12-27 17:28:16 +0000  (tag: pymysql-0.4)
2010-09-03 00:55:29 +0000  (tag: pymysql-0.3)

Đây là một lĩnh vực mà PYMYSQL dường như tỏa sáng, và thậm chí có thể là một lợi thế so với MySQL-Connectorector-Python, vẫn còn dưới áo choàng của BugTracker quá lớn của MySQL dưới quyền sở hữu của Oracle nổi tiếng. Đối với một thư viện khóa nhỏ, thấp mà không có bất kỳ tài liệu thực tế nào và chỉ có 126 thử nghiệm, nó có 33 người đóng góp trên GitHub và theo yêu cầu kéo #285, khá cao. Bởi vì PYMYSQL nhỏ và đơn giản, nên nó cho vay để đóng góp và dường như làm rất tốt trong lĩnh vực này. Các nhà phát triển cho đến nay đã đáp ứng với các vấn đề và các yêu cầu kéo của tác giả.

Dựa trên các biểu đồ của người đóng góp GitHub, có vẻ như PYMYSQL đã có một thời gian tạm lắng vào năm 2012 nhưng đã được chọn lại sau đó vào năm 2013. Tính đến năm 2012, nhà phát triển nổi bật nhất của nó Pete Hunt đã ngừng phát triển, và vào ngày 25 tháng 7 năm 2013 đã thêm một ghi chú cho README rằng The Readme rằng The Readme rằng The Readme rằng The Readme rằng Dự án đang tìm kiếm một người bảo trì mới. Tính đến năm 2013, nó đã được các nhà phát triển nổi tiếng nhất hiện tại Marcel Rodrigues (tên người dùng GitHub Lecram) và Inada Naoki (Github username methane).

Hầu hết các vấn đề đã được ghi nhận cho đến nay trong các lĩnh vực thử nghiệm, tài liệu và kiến ​​trúc đều rất dễ sửa chữa; Nếu cộng đồng OpenStack có thể cung cấp các nguồn lực để giải quyết một số lĩnh vực này và nếu các nhà phát triển PYMYSQL mở hợp lý để chấp nhận các thay đổi mới và tạo ra các bản phát hành mới một cách kịp thời, trình điều khiển PYMYSQL có thể nhanh chóng trở thành một đối thủ đáng gờm hoàn toàn trong lĩnh vực trình điều khiển MySQL .

Phụ lục A - Kiểm tra hiệu suất

import cProfile
import StringIO
import pstats
import contextlib
import time


@contextlib.contextmanager
def profiled(dbapi):
    pr = cProfile.Profile()
    pr.enable()
    yield
    pr.disable()
    s = StringIO.StringIO()
    ps = pstats.Stats(pr, stream=s).sort_stats('cumulative')
    ps.print_stats()
    print "DBAPI:  %s" % dbapi
    print s.getvalue()


@contextlib.contextmanager
def timeonly(dbapi):
    now = time.time()
    try:
        yield
    finally:
        total = time.time() - now
        print "DBAPI:  %s, total seconds %f" % (dbapi, total)

import MySQLdb
import pymysql
from mysql import connector as mysqlconnector


def go(dbapi, ctx):
    conn = dbapi.connect(
        user='scott', passwd='tiger', host='localhost', db='test')
    cursor = conn.cursor()
    cursor.execute("""
CREATE TABLE IF NOT EXISTS test_things (
    x INTEGER,
    y VARCHAR(255),
    z FLOAT
) engine=InnoDB
""")
    cursor.execute("DELETE from test_things")

    with ctx(dbapi):
        for row in xrange(1000):
            cursor.execute(
                "INSERT INTO test_things (x, y, z) "
                "VALUES (%(x)s, %(y)s, %(z)s)",
                {"x": row, "y": "row number %d" % row,
                 "z": row * 4.57292, }
            )

        for x in xrange(500):
            cursor.execute(
                "select * from test_things")
            for row in cursor.fetchall():
                row[0], row[1], row[2]

    cursor.close()
    conn.close()

go(pymysql, profiled)
go(mysqlconnector, profiled)
go(MySQLdb, profiled)

go(pymysql, timeonly)
go(mysqlconnector, timeonly)
go(MySQLdb, timeonly)
DBAPI:  
         26851003 function calls in 15.924 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1500    0.010    0.000   15.923    0.011 /Users/classic/dev/PyMySQL/pymysql/cursors.py:105(execute)
     1500    0.003    0.000   15.883    0.011 /Users/classic/dev/PyMySQL/pymysql/cursors.py:269(_query)
     1500    0.004    0.000   15.859    0.011 /Users/classic/dev/PyMySQL/pymysql/connections.py:746(query)
     1500    0.003    0.000   15.819    0.011 /Users/classic/dev/PyMySQL/pymysql/connections.py:892(_read_query_result)
     1500    0.004    0.000   15.812    0.011 /Users/classic/dev/PyMySQL/pymysql/connections.py:1097(read)
      500    0.003    0.000   15.559    0.031 /Users/classic/dev/PyMySQL/pymysql/connections.py:1154(_read_result_packet)
      500    0.900    0.002   15.429    0.031 /Users/classic/dev/PyMySQL/pymysql/connections.py:1187(_read_rowdata_packet)
   500000    3.417    0.000    9.173    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1200(_read_row_from_packet)
  2012000    1.157    0.000    5.307    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:311(read_length_coded_string)
   504500    1.495    0.000    5.209    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:845(_read_packet)
  2014500    1.248    0.000    3.035    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:293(read_length_encoded_integer)
  3539500    2.439    0.000    2.750    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:245(read)
  1009000    0.779    0.000    2.307    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:870(_read_bytes)
  1009000    1.197    0.000    1.423    0.000 {method 'read' of '_io.BufferedReader' objects}
   508500    0.379    0.000    0.695    0.000 /Users/classic/dev/PyMySQL/pymysql/util.py:3(byte2int)
  5058000    0.465    0.000    0.465    0.000 {len}
   500500    0.222    0.000    0.455    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1146(_check_packet_is_eof)
   504500    0.205    0.000    0.375    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:342(check_error)
  2504000    0.275    0.000    0.275    0.000 {method 'append' of 'list' objects}
   501500    0.182    0.000    0.230    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:326(is_eof_packet)
     3500    0.009    0.000    0.226    0.000 /Users/classic/dev/PyMySQL/pymysql/_socketio.py:45(readinto)
     3500    0.207    0.000    0.207    0.000 {method 'recv_into' of '_socket.socket' objects}
  1022000    0.203    0.000    0.203    0.000 {_struct.unpack}
   526000    0.200    0.000    0.200    0.000 {isinstance}
  1501000    0.195    0.000    0.195    0.000 {method 'get' of 'dict' objects}
   504500    0.176    0.000    0.176    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:238(__init__)
   504500    0.170    0.000    0.170    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:339(is_error_packet)
  2014500    0.167    0.000    0.167    0.000 {ord}
      500    0.006    0.000    0.125    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1224(_get_descriptions)
     2000    0.003    0.000    0.087    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:361(__init__)
     2000    0.019    0.000    0.084    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:365(__parse_field_descriptor)
   500000    0.056    0.000    0.056    0.000 /Users/classic/dev/PyMySQL/pymysql/converters.py:301(through)
     1500    0.005    0.000    0.037    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:915(_execute_command)
     1500    0.003    0.000    0.027    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:886(_write_bytes)
     1500    0.002    0.000    0.024    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py:223(meth)
     1500    0.021    0.000    0.021    0.000 {method 'sendall' of '_socket.socket' objects}
     1500    0.020    0.000    0.020    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:276(_do_get_result)
     1000    0.003    0.000    0.019    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:95(_escape_args)
     4000    0.002    0.000    0.015    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:99()
     1000    0.002    0.000    0.014    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1127(_read_ok_packet)
     3000    0.003    0.000    0.013    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:712(escape)
     1000    0.005    0.000    0.012    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:416(__init__)
     8000    0.011    0.000    0.011    0.000 {method 'decode' of 'str' objects}
     3500    0.003    0.000    0.007    0.000 {method '_checkReadable' of '_io._IOBase' objects}
     2000    0.003    0.000    0.006    0.000 /Users/classic/dev/PyMySQL/pymysql/converters.py:19(escape_item)
     4000    0.002    0.000    0.006    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:126()
     7500    0.003    0.000    0.005    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:115(ensure_bytes)
     2000    0.003    0.000    0.005    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:386(description)
     5500    0.004    0.000    0.004    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:268(advance)
     1000    0.001    0.000    0.004    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:722(escape_string)
     3500    0.004    0.000    0.004    0.000 /Users/classic/dev/PyMySQL/pymysql/_socketio.py:87(readable)
      500    0.002    0.000    0.004    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:442(__init__)
     3500    0.003    0.000    0.003    0.000 {method '_checkClosed' of '_io._IOBase' objects}
     1000    0.001    0.000    0.003    0.000 /Users/classic/dev/PyMySQL/pymysql/converters.py:59(escape_string)
     1500    0.003    0.000    0.003    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1080(__init__)
     1500    0.001    0.000    0.003    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:92(nextset)
     4000    0.002    0.000    0.002    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:397(get_column_length)
     1000    0.002    0.000    0.002    0.000 /Users/classic/dev/PyMySQL/pymysql/converters.py:56(escape_float)
     1000    0.002    0.000    0.002    0.000 {method 'sub' of '_sre.SRE_Pattern' objects}
     3000    0.002    0.000    0.002    0.000 {_struct.pack}
     6000    0.002    0.000    0.002    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:62(_get_db)
     1500    0.001    0.000    0.002    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:80(_nextset)
     1500    0.001    0.000    0.001    0.000 /Users/classic/dev/PyMySQL/pymysql/util.py:9(int2byte)
      500    0.001    0.000    0.001    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:244(fetchall)
     1500    0.001    0.000    0.001    0.000 {min}
     2500    0.001    0.000    0.001    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:323(is_ok_packet)
     1000    0.001    0.000    0.001    0.000 /Users/classic/dev/PyMySQL/pymysql/converters.py:52(escape_int)
     2000    0.001    0.000    0.001    0.000 {method 'items' of 'dict' objects}
     1500    0.001    0.000    0.001    0.000 {getattr}
     1500    0.000    0.000    0.000    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:1093(__del__)
     1000    0.000    0.000    0.000    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:259(read_all)
      500    0.000    0.000    0.000    0.000 /Users/classic/dev/PyMySQL/pymysql/cursors.py:67(_check_executed)
      500    0.000    0.000    0.000    0.000 /Users/classic/dev/PyMySQL/pymysql/connections.py:336(is_load_local_packet)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py:21(__exit__)
        1    0.000    0.000    0.000    0.000 test.py:8(profiled)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
DBAPI:  
         11674074 function calls in 19.049 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      500    0.640    0.001   18.556    0.037 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:820(fetchall)
      500    0.003    0.000   11.196    0.022 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:655(get_rows)
      500    1.561    0.003   11.191    0.022 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:292(read_text_result)
   504500    3.303    0.000    7.306    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/network.py:219(recv_plain)
   500000    3.572    0.000    6.625    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:359(row_to_python)
  1009000    3.155    0.000    3.155    0.000 {method 'recv_into' of '_socket.socket' objects}
   500000    2.049    0.000    2.329    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/utils.py:220(read_lc_string_list)
   500000    0.653    0.000    2.116    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:531(_STRING_to_python)
   502000    0.378    0.000    1.329    0.000 {method 'decode' of 'bytearray' objects}
   502000    0.221    0.000    0.951    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py:15(decode)
   502000    0.730    0.000    0.730    0.000 {_codecs.utf_8_decode}
   500000    0.514    0.000    0.514    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:413(_INT_to_python)
   509500    0.510    0.000    0.510    0.000 {_struct.unpack_from}
     1500    0.009    0.000    0.492    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:452(execute)
     1500    0.004    0.000    0.437    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:705(cmd_query)
   500000    0.367    0.000    0.367    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:405(_FLOAT_to_python)
   504500    0.343    0.000    0.343    0.000 {method 'extend' of 'bytearray' objects}
     1500    0.007    0.000    0.315    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:481(_send_cmd)
  2501500    0.275    0.000    0.275    0.000 {method 'append' of 'list' objects}
   500500    0.246    0.000    0.246    0.000 {method 'startswith' of 'bytearray' objects}
   524002    0.150    0.000    0.150    0.000 {isinstance}
     1500    0.011    0.000    0.118    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:613(_handle_result)
  1004500    0.112    0.000    0.112    0.000 {len}
   500000    0.092    0.000    0.092    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:204(description)
     1500    0.007    0.000    0.042    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/network.py:118(send_plain)
     2000    0.013    0.000    0.041    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:226(parse_column)
     1000    0.008    0.000    0.034    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:346(_process_params_dict)
     1500    0.002    0.000    0.029    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py:223(meth)
     1500    0.026    0.000    0.026    0.000 {method 'sendall' of '_socket.socket' objects}
     5000    0.007    0.000    0.014    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/catch23.py:79(struct_unpack)
     1000    0.001    0.000    0.013    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:562(_handle_ok)
    12000    0.011    0.000    0.011    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/utils.py:167(read_lc_string)
     1000    0.004    0.000    0.010    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:199(parse_ok)
     3000    0.005    0.000    0.009    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:152(to_mysql)
     1500    0.003    0.000    0.007    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:118(make_command)
     3000    0.003    0.000    0.007    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:130(quote)
     1500    0.005    0.000    0.006    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/network.py:53(_prepare_packets)
     1500    0.003    0.000    0.006    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:406(_handle_result)
     3000    0.003    0.000    0.006    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:102(escape)
     1000    0.002    0.000    0.006    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:252(parse_eof)
      500    0.001    0.000    0.005    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:579(_handle_eof)
     2000    0.003    0.000    0.005    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:545(_handle_server_status)
     1500    0.003    0.000    0.004    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/utils.py:53(int1store)
     3000    0.003    0.000    0.003    0.000 {method 'encode' of 'str' objects}
     9001    0.003    0.000    0.003    0.000 {method 'replace' of 'str' objects}
     1500    0.003    0.000    0.003    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:295(_reset_result)
     4500    0.003    0.000    0.003    0.000 {_struct.pack}
     2500    0.003    0.000    0.003    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/utils.py:296(read_lc_int)
      500    0.002    0.000    0.003    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:757(_handle_eof)
     6027    0.003    0.000    0.003    0.000 {method 'format' of 'str' objects}
     3000    0.002    0.000    0.003    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:1221(_set_unread_result)
      500    0.001    0.000    0.002    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/protocol.py:219(parse_column_count)
     1000    0.002    0.000    0.002    0.000 {repr}
     4527    0.002    0.000    0.002    0.000 {getattr}
     4000    0.002    0.000    0.002    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/constants.py:34(flag_is_set)
     1000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:383(_handle_noresultset)
     4000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:1233(_get_unread_result)
     2001    0.001    0.000    0.001    0.000 {method 'items' of 'dict' objects}
      500    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:307(_have_unread_result)
     3000    0.001    0.000    0.001    0.000 {method 'lower' of 'str' objects}
      500    0.001    0.000    0.001    0.000 {range}
     1000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:173(_str_to_mysql)
     1000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:169(_float_to_mysql)
     1000    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/conversion.py:161(_int_to_mysql)
     1500    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/connection.py:1313(_get_getwarnings)
     1500    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:200(reset)
      500    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mysql/connector/cursor.py:397(_handle_resultset)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/__init__.py:71(search_function)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/ascii.py:41(getregentry)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py:21(__exit__)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/__init__.py:49(normalize_encoding)
        1    0.000    0.000    0.000    0.000 test.py:8(profiled)
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/codecs.py:77(__new__)
        1    0.000    0.000    0.000    0.000 {__import__}
        3    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x1001534e8}
        1    0.000    0.000    0.000    0.000 {method 'translate' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {hasattr}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
DBAPI:  
         47503 function calls in 0.918 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1500    0.009    0.000    0.917    0.001 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:164(execute)
     1500    0.002    0.000    0.890    0.001 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:353(_query)
     1500    0.004    0.000    0.498    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:315(_do_query)
     1500    0.016    0.000    0.391    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:358(_post_get_result)
     1500    0.001    0.000    0.375    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:324(_fetch_row)
      500    0.374    0.001    0.374    0.001 {built-in method fetch_row}
     1500    0.007    0.000    0.362    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:142(_do_get_result)
     1500    0.002    0.000    0.351    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:351(_get_result)
     1500    0.349    0.000    0.349    0.000 {method 'store_result' of '_mysql.connection' objects}
     1500    0.131    0.000    0.131    0.000 {method 'query' of '_mysql.connection' objects}
     4000    0.002    0.000    0.010    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:184()
     3000    0.002    0.000    0.008    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/connections.py:267(literal)
     1500    0.007    0.000    0.007    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:107(_warning_check)
     3000    0.002    0.000    0.006    0.000 {method 'escape' of '_mysql.connection' objects}
     6000    0.002    0.000    0.002    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:159(_get_db)
     1000    0.002    0.000    0.002    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/converters.py:81(Float2Str)
     2500    0.001    0.000    0.001    0.000 {isinstance}
     1000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/connections.py:202(string_literal)
      500    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:380(fetchall)
      500    0.001    0.000    0.001    0.000 {built-in method describe}
     1000    0.001    0.000    0.001    0.000 {method 'string_literal' of '_mysql.connection' objects}
     1500    0.001    0.000    0.001    0.000 {method 'insert_id' of '_mysql.connection' objects}
     1500    0.001    0.000    0.001    0.000 {method 'affected_rows' of '_mysql.connection' objects}
     1000    0.001    0.000    0.001    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/converters.py:69(Thing2Str)
     1500    0.000    0.000    0.000    0.000 {method 'warning_count' of '_mysql.connection' objects}
     1500    0.000    0.000    0.000    0.000 {method 'info' of '_mysql.connection' objects}
     1000    0.000    0.000    0.000    0.000 {method 'iteritems' of 'dict' objects}
      500    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQLdb/cursors.py:103(_check_executed)
      500    0.000    0.000    0.000    0.000 {len}
      500    0.000    0.000    0.000    0.000 {built-in method field_flags}
        1    0.000    0.000    0.000    0.000 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py:21(__exit__)
        1    0.000    0.000    0.000    0.000 test.py:8(profiled)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
DBAPI:  , total seconds 10.046012
DBAPI:  , total seconds 15.403260
DBAPI:  , total seconds 1.028737

Sự khác biệt giữa MySQL và PYMYSQL là gì?

PYMYSQL và MySQLDB cung cấp chức năng tương tự - cả hai đều là đầu nối cơ sở dữ liệu.Sự khác biệt là trong việc triển khai trong đó MySQLDB là một phần mở rộng C và PYMYSQL là trăn tinh khiết.Có một vài lý do để thử PYMYSQL: có thể dễ dàng chạy trên một số hệ thống hơn.MySQLdb is a C extension and PyMySQL is pure Python. There are a few reasons to try PyMySQL: it might be easier to get running on some systems.

PYMYSQL là gì?

PYMYSQL là một giao diện để kết nối với máy chủ cơ sở dữ liệu MySQL từ Python.Nó thực hiện cơ sở dữ liệu Python API v2.0 và chứa một thư viện máy khách MySQL Pure-Python.Mục tiêu của PYMYSQL là là một sự thay thế thả vào cho MySQLDB.an interface for connecting to a MySQL database server from Python. It implements the Python Database API v2. 0 and contains a pure-Python MySQL client library. The goal of PyMySQL is to be a drop-in replacement for MySQLdb.

Trình kết nối MySQL tốt nhất là gì?

Danh sách 5 đầu nối Python SQL hàng đầu..
PyMySQL..
MySQLdb..
QTSQL..
Psycopg2..
SuperSQLite..

Tôi có cần kết nối python cho mysql không?

Python cần một trình điều khiển MySQL để truy cập cơ sở dữ liệu MySQL.Trong hướng dẫn này, chúng tôi sẽ sử dụng trình điều khiển "Đầu nối MySQL".Chúng tôi khuyên bạn nên sử dụng PIP để cài đặt "Đầu nối MySQL".PIP rất có thể đã được cài đặt trong môi trường Python của bạn.. In this tutorial we will use the driver "MySQL Connector". We recommend that you use PIP to install "MySQL Connector". PIP is most likely already installed in your Python environment.