Impor bersyarat modul dengan Python

143

Dalam program saya, saya ingin mengimpor simplejson atau json berdasarkan apakah OS yang digunakan pengguna adalah Windows atau Linux. Saya mengambil nama OS sebagai masukan dari pengguna. Sekarang, apakah benar melakukan hal berikut?

osys = raw_input("Press w for windows,l for linux")
if (osys == "w"):
    import json as simplejson
else:
    import simplejson  
Tim
sumber
33
Mengapa Anda mengambil nama os sebagai masukan dari pengguna? Lihat modul platform. docs.python.org/library/platform.html platform.platform() atau platform.system()harus melakukan apa yang Anda butuhkan, daripada meminta pengguna untuk memasukkan sesuatu setiap kali kode dijalankan.
Joe Kington
57
@ S. Lott: serius? Anda tahu bahwa suara naik / turun dimaksudkan untuk mencerminkan kualitas pertanyaan , bukan? Dan bukan apakah Anda setuju dengan sesuatu yang lain dalam kode OP.
jalf
2
@jalf: Ini pertanyaan yang buruk dalam segala hal kecuali tata bahasa. Ini tidak boleh ditemukan sebagai respons teratas untuk segala jenis penelusuran.
S. Lott
12
@ S.Lott Tidak ada yang salah dengan ingin tahu apakah impor bersyarat itu pythonic. Dan jelas orang lain setuju karena memiliki +50 suara lebih meskipun Anda berusaha.
SARose
Prinsip terkait: stackoverflow.com/questions/11360858/…
Brandon Bertelsen

Jawaban:

186

Saya telah melihat idiom ini banyak digunakan, jadi Anda bahkan tidak perlu melakukan OS sniffing:

try:
    import json
except ImportError:
    import simplejson as json
Matt Williamson
sumber
18
Anda harus mencoba mengimpor terlebih dahulu simplejson as jsonkarena kemungkinan ini adalah versi jsonmodul standar yang lebih baru (lebih cepat) .
Seppo Erviälä
atau ujsonuntuk kecepatan
lababidi
61

Untuk menjawab pertanyaan dalam judul Anda tetapi bukan kasus tertentu yang Anda berikan, itu benar sekali, banyak paket melakukan ini. Mungkin lebih baik untuk mencari tahu OS sendiri daripada mengandalkan pengguna; inilah pySerial melakukannya sebagai contoh.

serial/__init__.py

import sys

if sys.platform == 'cli':
    from serial.serialcli import Serial
else:
    import os
    # chose an implementation, depending on os
    if os.name == 'nt':  # sys.platform == 'win32':
        from serial.serialwin32 import Serial
    elif os.name == 'posix':
        from serial.serialposix import Serial, PosixPollSerial, VTIMESerial  # noqa
    elif os.name == 'java':
        from serial.serialjava import Serial
    else:
        raise ImportError(
            "Sorry: no implementation for your platform ('{}') available".format(
                os.name
            )
        )

Ini harus digunakan hanya dalam kasus di mana Anda berasumsi dan membutuhkan jaminan kuat bahwa antarmuka / fitur tertentu akan ada di sana: misalnya 'file' dipanggil /dev/ttyX. Dalam kasus Anda: berurusan dengan JSON, tidak ada yang benar-benar spesifik untuk OS dan Anda hanya memeriksa apakah paket tersebut ada atau tidak. Dalam hal ini, cukup tryuntuk mengimpornya, dan kembali dengan exceptjika gagal:

try:
    import some_specific_json_module as json
except ImportError:
    import json
Nick T.
sumber
11
Tidak, sangat tidak tepat untuk nama OS hardcode untuk memutuskan apakah simplejsonatau jsontersedia. Anda mengutip kode dari impor khusus OS , yang merupakan kasus yang sangat berbeda. Lihat jawaban Matt untuk pendekatan yang benar.
Glenn Maynard
17
@ Glenn Maynard: Kalau begitu saya akan tunduk kepada Anda; Saya tidak pernah menggunakan jsonpaket tersebut dan mencoba menjawab pertanyaan yang lebih umum "dapatkah Anda melakukan impor modul bersyarat".
Nick T
7

Tidak disarankan untuk menggunakan json atau simplejson dengan platform OS. simplejson adalah versi json yang lebih baru dan lanjutan jadi kita harus mencoba mengimpornya terlebih dahulu.

Berdasarkan versi python Anda dapat mencoba cara di bawah ini untuk mengimpor json atau simplejson

import sys
if sys.version_info > (2, 7):
    import simplejson as json
else:
    import json
Aashutosh jha
sumber