2010-05-03 38 views
22

Tôi phải lấy tên phân phối Linux từ tập lệnh Python. Có một phương pháp dist trong module nền tảng:Kiểm tra tên phân phối Linux

import platform 
platform.dist() 

Nhưng dưới Arch Linux của tôi nó sẽ trả về:

>>> platform.dist() 
('', '', '') 

Tại sao? Làm thế nào tôi có thể nhận được tên?

PS. Tôi phải kiểm tra xem bản phân phối có dựa trên Debian hay không.


Cập nhật: Tôi tìm thấy tại đây Python site, mà dist() không còn được dùng kể từ 2.6.

>>> platform.linux_distribution() 
('', '', '') 
+0

@Kimvais Ý tôi là lấy tên chính xác từ tập lệnh python mà không cần phân tích cú pháp bất kỳ tệp nào, chỉ có các phương thức standart. – Ockonal

+0

'uname -a' trở về Arch là gì? platform.py là 1600 dòng thử tất cả mọi thứ mà họ có thể nghĩ đến để phân biệt các hệ thống khác nhau; nó là một đống khổng lồ của heuristics. Arch cũng dường như chỉ dựa vào chính nó, không có bản phân phối nào khác: http://en.wikipedia.org/wiki/Arch_Linux – msw

+0

'Lsb_release -is' trả về dưới Arch là gì? Nếu 'platform.dist()' cung cấp cho bạn không có dữ liệu có thể sử dụng, có thể bạn có thể gọi 'subprocess.check_output ([" lsb_release "," - is "])' thay thế. – panzi

Trả lời

9

này làm việc cho tôi trên Ubuntu:

('Ubuntu', '10.04', 'lucid') 

sau đó tôi sử dụng strace để tìm hiểu chính xác những gì các module nền tảng đang làm để tìm ra phân phối, và nó là một phần này:

open("/etc/lsb-release", O_RDONLY|O_LARGEFILE) = 3 
fstat64(3, {st_mode=S_IFREG|0644, st_size=102, ...}) = 0 
fstat64(3, {st_mode=S_IFREG|0644, st_size=102, ...}) = 0 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76b1000 
read(3, "DISTRIB_ID=Ubuntu\nDISTRIB_RELEAS"..., 8192) = 102 
read(3, "", 4096)      = 0 
read(3, "", 8192)      = 0 
close(3)        = 0 

Vì vậy, có /etc/lsb-release chứa thông tin này, xuất phát từ gói Debian base-files của Ubuntu.

+0

Lưu ý rằng đôi khi tập tin là '/ etc/os-release'. – panzi

12

Here 's những gì tôi tìm thấy:

platform.linux_distribution 

cố gắng xác định tên của tên phân phối Linux OS.

Nó nói platform.dist không còn được dùng kể từ 2.6, bạn phải sử dụng platform.linux_distribution bằng Python 2 (nhưng cũng không được dùng nữa trong Python 3.5).

0

Hai tùy chọn cho bạn:

  1. Sử dụng nhập nền tảng platform.linux_distribution() # Giống như ('Ubuntu', '9.10', 'duyên')

  2. Hoặc bạn chỉ có thể đọc nội dung của/etc/debian_version ("squeeze/sid") hoặc/etc/lsb-release sẽ cung cấp:

    DISTRIB_ID=Ubunt 
    DISTRIB_RELEASE=9.10 
    DISTRIB_CODENAME=karmic 
    DISTRIB_DESCRIPTION="Ubuntu 9.10" 
    
+0

Thật không may, tùy chọn đầu tiên không hoạt động trên Arch Linux. Tôi không có quyền truy cập vào Arch vào lúc này, vì vậy tôi không thể kiểm tra tùy chọn thứ hai. –

4

Nó hoạt động ở đây. Và không, Arch Linux không phải dựa trên Debian.

>>> import platform 
>>> platform.dist() 
('SuSE', '11.2', 'x86_64') 

Vì vậy, Python không biết cách lấy thông tin phát hành của Arch Linux và đã tìm kiếm bản phát hành/etc/redhat-release và/etc/SuSE.

platform.dist() là một chức năng lỗi thời. Bạn nên sử dụng nền tảng.linux_distribution()

Trên thực tế, trên hệ thống của tôi nó mang lại một kết quả khác nhau:

>>> platform.linux_distribution() 
('openSUSE ', '11.2', 'x86_64') 

platform.linux_distribution() trông trong/etc file chứa "giải phóng" hay "phiên bản" như chuỗi. Nó cũng tìm trong tệp phát hành LSB chuẩn. Nếu cuối cùng không hoạt động, nó sẽ chuyển sang một hàm _dist_try_harder cố gắng lấy thông tin từ những nơi khác.

Vì vậy, việc Arch Linux cung cấp thông tin phát hành LSB chuẩn hoặc để vá Python sử dụng "cách" của họ.

-1

Bạn có lẽ sẽ phải nghỉ mát để:

if platform.linux_distribution() == ('', '', ''): 
    # do something specific to look for Arch 

hoặc bạn luôn có thể làm tăng thêm lib/python2.6/platform.py và gửi những thay đổi của bạn.

+1

Loại so sánh này rất nguy hiểm vì Arch Linux không phải là bản phân phối duy nhất mà 'nền tảng' không thể phát hiện được. Amazon Linux cũng dẫn đến một tuple rỗng. –

1

này làm việc cho tôi dưới Ubuntu và Manjaro:

def get_distro(): 
    """ 
    Name of your Linux distro (in lowercase). 
    """ 
    with open("/etc/issue") as f: 
     return f.read().lower().split()[0] 
+0

Điều này hoạt động theo Arch Linux;) – nachopro

+1

ý tưởng không tốt, '/ etc/issue' là hiển thị dòng chào mừng trên bàn điều khiển tiêu chuẩn và thường được sửa đổi bởi người dùng/quản trị viên. Cách tiêu chuẩn để phát hiện bản phân phối hiện đại là phân tích cú pháp '/ etc/lsb-release' hoặc tốt hơn'/etc/os-release' –

0

Python 2 không đúng cách phát hiện Arch Linux. Điều này đã được cố định bằng Python 3.3+, nhưng không bao giờ được back-chuyển đến Python 2. Dưới đây là một vài báo cáo lỗi chính thức:

https://bugs.python.org/issue20454
https://bugs.python.org/issue11678

Một cách giải quyết cho vấn đề này bằng Python 2 là khá đơn giản. Bạn chỉ cần nói với mô-đun nền tảng rằng "vòm" là bản phân phối được hỗ trợ:

>>> import platform 
>>> platform.linux_distribution(supported_dists=platform._supported_dists + ('arch',)) 
('arch', '', '') 

Lưu ý rằng Arch Linux là bản phát hành, vì vậy nó không có phiên bản hoặc id.

Đối số supported_dists được ghi thành tài liệu here, mặc dù tôi không tìm thấy tài liệu rất rõ ràng. Bạn không muốn ghi đè _supported_dists vì sau đó mã của bạn sẽ chỉ hoạt động trên Arch Linux. Bạn muốn nối thêm vào bộ tuple.

Thực tế, nếu bạn in ra giá trị platform._supported_dists, bạn sẽ thấy rằng sự khác biệt duy nhất giữa Python 2.7.12 và Python 3.5.1 là bổ sung ('arch', 'mageia'). Thực tế thú vị: bạn cũng có thể nối thêm 'system' để phát hiện nền tảng trên Amazon Linux.

2

Lý do vì vậy mà platform.linux_distribution không xác định một số bản phân phối là do các bản phân phối cách không chuẩn hóa cung cấp thông tin liên quan đến phiên bản trên chính chúng.

Tôi đã viết một gói có tên là distro (hiện được sử dụng bởi pip) nhằm thay thế distro.linux_distribution. Nó hoạt động trên nhiều bản phân phối có thể trả về các bộ dữ liệu rỗng hoặc rỗng khi sử dụng platform.

https://github.com/nir0s/distro (distro, trên pypi)

Nó cung cấp một API nhiều phức tạp hơn để lấy thông tin phân phối liên quan.

$ python 
Python 2.7.12 (default, Nov 7 2016, 11:55:55) 
[GCC 6.2.1 20160830] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import distro 
>>> distro.linux_distribution() 
(u'Antergos Linux', '', u'ARCHCODE') 

Nhân tiện, platform.linux_distribution sẽ bị xóa trong Python 3.7.

Các vấn đề liên quan