Xóa con trỏ được sử dụng trong SearchCthon trong phạm vi hiểu từ điển?


12

Nếu tốt nhất là mở các con trỏ bằng cách sử dụng câu lệnh with để đảm bảo nó bị xóa, như vậy:

with arcpy.da.UpdateCursor(fc,fields) as cursor:

Sau đó, nếu một con trỏ được sử dụng như là lần lặp theo cách hiểu như vậy:

d = {k:v for (k,v) in arcpy.da.SearchCursor(fc,fields)}

Có nhất thiết phải xóa con trỏ sau khi sử dụng nó trong phần hiểu không?


1
Câu hỏi tuyệt vời. Bạn đang cố gắng để xử lý khóa lược đồ? Có một số bài đăng sớm (chủ yếu là lỗi thời) về một chủ đề tương tự, mặc dù tôi không thể tìm thấy một nguồn chính xác trên các dacon trỏ mới : sgillies.net/2011/02/01/get-with-it.htmlhelp.arcgis.com/ vi / arcgisdesktop / 10.0 / help / index.html # // . Cụ thể, hãy xem ý kiến ​​của @JasonScheirer ở cuối liên kết đầu tiên.
Aaron

Câu trả lời:


13

Cho dù nó thực sự cần thiết là câu hỏi sai. Câu hỏi là liệu đó có phải là một ý tưởng tốt.

Theo quy định trong lập trình, bạn nên tránh làm những điều kỳ lạ và sử dụng công cụ tốt nhất cho công việc . Nếu một cái gì đó có một cách rõ ràng để phát hành tài nguyên, chỉ cần làm cho bản phát hành rõ ràng và được thực hiện với nó:

with arcpy.da.UpdateCursor(fc,fields) as cursor:
    d = {k: v for (k,v) in cursor}

Những gì bạn có thể không nhận thức được là withmệnh đề thực sự gọi logic bổ sung. Một withmệnh đề yêu cầu một trình quản lý bối cảnh, phải có một phương thức __enter__(được gọi khi khối được nhập) và __exit__(được gọi khi khối được thoát). Cụ thể, __exit__phương thức được gọi bất kể có xảy ra ngoại lệ hay không, đảm bảo chương trình luôn giải phóng tài nguyên ngay cả khi có lỗi. Điều này cung cấp cho mã của bạn tài liệu rõ ràng về thời điểm tài nguyên được mua và khi nào nó được phát hành và nó đảm bảo rằng tài nguyên có thể được phát hành càng sớm càng tốt.

Ngược lại, bạn thực sự không thể phụ thuộc vào thời gian chạy để đóng nó ngay lập tức cho bạn. Điều này là do cách nó bị đóng bằng cách gọi hàm hủy của đối tượng, điều này có thể xảy ra hoặc không xảy ra ngay lập tức. Python không đảm bảo khi nào một hàm hủy được gọi, chỉ có điều nó sẽ xuất hiện khi đối tượng được thu gom rác. (Xem tại đây .) Hiện tại, Python được triển khai để nó xảy ra ngay khi không còn tham chiếu đến một đối tượng. Nhưng thật dễ dàng để vô tình truyền các tham chiếu đến một đối tượng và thời gian chạy của Python có thể thay đổi.

Cũng xem xét việc bảo trì dài hạn. Không có tài liệu tham khảo lâu dài với nó bây giờ, nhưng những gì xảy ra trong 6 tháng khi bạn cần phải sửa đổi mã để có một tài liệu tham khảo? Nếu người khác làm điều đó thì sao? Người thực hiện thay đổi có thể không nghĩ sẽ chuyển sang một withkhối vì chưa có ai ở đó. Làm sạch tài nguyên của bạn thành thói quen và bạn sẽ có ít vấn đề hơn với nó.

Bạn có thực sự muốn buộc mã của mình vào chi tiết triển khai của bộ sưu tập rác không? Bạn có muốn phải liên tục suy nghĩ về việc liệu bạn có thể vô tình tuyên truyền một tài liệu tham khảo thông qua một ngoại lệ không? Không, bạn không. Hãy tưởng tượng nếu điều đó xảy ra khi tập lệnh được gọi trong ArcMap. Người dùng sẽ bị buộc phải đóng toàn bộ quá trình chỉ để phát hành tệp. Vì vậy, đừng đặt mình vào vị trí đó. Phát hành tài nguyên một cách rõ ràng. Lưu một dòng mã không có giá trị rủi ro của các vấn đề nó có thể gây ra. Các trình quản lý bối cảnh là cơ chế tiêu chuẩn để có được và giải phóng tài nguyên trong Python và họ làm điều đó rất tốt.

Điểm mấu chốt là không phát hành nó một cách rõ ràng là một ý tưởng tồi.

Tất nhiên, điều này giả định rằng mã có một số khả năng ảnh hưởng đến người khác, như đưa nó vào một tập lệnh mà người khác sẽ cần chạy hoặc duy trì hoặc nó có thể trì hoãn việc phân phối công việc của bạn nếu bạn phải đóng ArcMap hoàn toàn vì bạn không thể lưu các thay đổi của bạn. Nếu bạn là người duy nhất sẽ bị ảnh hưởng bởi một vấn đề, thì bằng mọi cách, hãy bay lên khi đối mặt với những thực hành tốt mà bạn muốn.


3

Không, không cần thiết phải xóa một cursorsau khi sử dụng nó trong một sự hiểu biết. A cursorlà một thể hiện của một lớp, là một đối tượng (mọi thứ trong python là một đối tượng). Mỗi phiên python có một namespacetham chiếu chứa tất cả các đối tượng trong phiên - nghĩ về nó giống như một từ điển trong đó các khóa là tham chiếu đến từng đối tượng và các giá trị là chính các đối tượng. Khi 'số tham chiếu' - số lượng khóa tham chiếu đến đối tượng đó - giảm về 0, đối tượng sẽ bị xóa và bộ nhớ được phân bổ lại . Khi bạn sử dụng một cursorcách hiểu, không có tham chiếu đến đối tượng đó trong không gian tên. Sau khi hiểu xong, đối tượng sẽ bị xóa.

Không có mục trong không gian tên, và do đó không cần phải xóa bất cứ điều gì. ESRI cũng minh họa cú pháp này trong ví dụ 2, ở đây .

Để làm rõ hơn, nếu bạn chạy:

>>> import arcpy
>>> f = r'C:\Workspace\study_area.shp'
>>> a = arcpy.da.SearchCursor(f, ['*'])

Bạn sẽ thấy một tệp .lock xuất hiện trong thư mục (kiểm tra trình duyệt tệp của bạn). Tham chiếu đến con trỏ là a, điều này sẽ làm cho cursor(và do đó khóa) tồn tại cho đến khi abị xóa. Vì vậy, khi bạn chạy:

>>> del(a)

Mục trong không gian tên sẽ bị xóa và khóa sẽ giải phóng (tệp .lock sẽ biến mất). Nếu bạn chạy:

>>> t = [i for i in arcpy.da.SearchCursor(f, ['*'])]

Bạn sẽ không thấy tệp khóa hoặc nó sẽ biến mất khi lệnh hoàn thành. Không có một mục trong không gian tên, cursorkhông tồn tại. tđề cập đến danh sách bạn vừa tạo, không cursorđược sử dụng để tạo nó.

Để tóm tắt, bạn chỉ cần lo lắng về việc xóa cursorskhi họ có một tham chiếu trong không gian tên (tức là khi bạn đã gán chúng cho một biến, như atrong ví dụ trên).


2
Đây là thực hành lập trình cực kỳ kém. Nếu một cái gì đó có một cách rõ ràng để phát hành tài nguyên, bạn sử dụng nó .
jpmc26

@ jpmc26, Phần nào là "thực hành lập trình cực kỳ kém"? Hiểu biết nói chung? Hoặc chỉ khi iterable được khởi tạo trong phạm vi hiểu? Tôi nghĩ rằng một lập luận mạnh mẽ cho cái sau là nó ngay lập tức giải phóng tài nguyên.
Tom

@Tom Không phát hành tài nguyên rõ ràng. Hiểu là công cụ tuyệt vời, và khởi tạo các vòng lặp bình thường bên trong chúng là hoàn toàn bình thường. Điều tồi tệ ở đây là các đối tượng con trỏ thu được khóa tệp và không có bản phát hành rõ ràng nào về chúng. Xem câu trả lời của tôi để biết thêm chi tiết.
jpmc26

2

Cập nhật và chèn con trỏ không thể được tạo cho bảng hoặc lớp đối tượng nếu có khóa độc quyền cho tập dữ liệu đó. Các hàm UpdateCthon hoặc insertCoder không thành công do khóa độc quyền trên tập dữ liệu. Nếu các hàm này tạo thành công một con trỏ, chúng sẽ áp dụng khóa độc quyền trên tập dữ liệu để hai tập lệnh không thể tạo cập nhật hoặc chèn con trỏ trên cùng một tập dữ liệu.

Trong Python, khóa vẫn tồn tại cho đến khi con trỏ được giải phóng. Mặt khác, tất cả các ứng dụng hoặc tập lệnh khác có thể bị ngăn chặn không cần thiết truy cập vào tập dữ liệu. Một con trỏ có thể được giải phóng bởi một trong những điều sau đây:

Bao gồm con trỏ bên trong câu lệnh with, sẽ đảm bảo giải phóng các khóa bất kể con trỏ có hoàn thành thành công hay không;

Gọi reset () trên con trỏ;

Việc hoàn thành con trỏ;

Hoàn toàn xóa con trỏ bằng câu lệnh del của Python - ESRI

Khóa với các con trỏ arcpy.da khá giống với khóa với các con trỏ arcpy ban đầu.

Sau khi kiểm tra mã của bạn và như gberard đã chỉ ra, không có tham chiếu nào đến con trỏ sau khi quá trình hiểu kết thúc.
Ngoài ra, không có khóa trên lớp tính năng sau khi sự hiểu biết kết thúc.


1
Xóa cái gì? Không có tham chiếu đến đối tượng con trỏ sau khi quá trình hiểu kết thúc, vì vậy về mặt lý thuyết, nó sẽ bị đóng lại. Việc triển khai ESRI có hành xử như bạn mong đợi hay không là một câu hỏi khác và tôi không nghĩ các tài liệu thực sự trả lời điều đó.
mikewatt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.