แนวทางปฏิบัติที่ดีในการตรวจสอบว่ามีตัวแปรด้านสิ่งแวดล้อมอยู่หรือไม่?


130

ฉันต้องการตรวจสอบสภาพแวดล้อมของฉันว่ามีตัวแปรหรือไม่พูด"FOO"ใน Python เพื่อจุดประสงค์นี้ฉันใช้ไฟล์osไลบรารีมาตรฐาน หลังจากอ่านเอกสารของห้องสมุดฉันได้ค้นพบ 2 วิธีในการบรรลุเป้าหมาย:

วิธีที่ 1:

if "FOO" in os.environ:
    pass

วิธีที่ 2:

if os.getenv("FOO") is not None:
    pass

ฉันต้องการทราบว่าวิธีใดเป็นเงื่อนไขที่ดี / เป็นที่ต้องการและเพราะเหตุใด


มันขึ้นอยู่กับความคิดเห็นเป็นหลัก ทั้งสองมีจุดประสงค์เดียวกัน ฉันจะชอบวิธีที่ 1 มากกว่าเพราะมันสะอาดกว่า
Moinuddin Quadri

1
ฉันไม่สามารถพูดได้ว่ามีอะไรอยู่ในนั้น เลือกหนึ่ง (พลิกเหรียญ?) และประเมินอีกครั้งในภายหลังหากปรากฎว่าไม่ได้ผล ตามตรงฉันคิดว่าคุณใช้เวลาพิมพ์คำถามนี้นานกว่าที่คุณจะประหยัดทั้งสองทาง!
jonrsharpe

1
@Ayoub: ฉันคิดว่าคุณลืมดูคำถาม"อะไรคือแนวทางปฏิบัติที่ดีในการตรวจสอบว่ามีตัวแปรสภาพแวดล้อมอยู่หรือไม่ใน Python"
Moinuddin Quadri

1
ตามความคิดเห็น ไวยากรณ์วิธีที่ 1 ทำงานได้ดีกว่าเนื่องจากคุณถามว่าfooอยู่ใน env vars หรือไม่ไม่ใช่หากต้องการfooผลลัพธ์ในNoneค่า
Uriel

1
แต่วิธีนั้นอาจไม่ชัดเจนเว้นแต่คุณเป็นชาวดัตช์ ...
jonrsharpe

คำตอบ:


168

ใช้ครั้งแรก; โดยตรงจะพยายามตรวจสอบว่ามีการกำหนดบางสิ่งไว้environหรือไม่ แม้ว่ารูปแบบที่สองทำงานเท่าเทียมกันดีก็ขาดความหมายตั้งแต่คุณจะได้รับกลับมาคุ้มค่าถ้ามันมีอยู่และเพียงใช้สำหรับการเปรียบเทียบ

คุณกำลังพยายามที่จะดูว่าสิ่งที่เป็นปัจจุบันใน environเหตุผลที่คุณจะได้รับเพียงเพื่อเปรียบเทียบมันแล้วโยนมันออกไป ?

นั่นคือสิ่งที่getenvทำ:

รับตัวแปรสภาพแวดล้อมส่งคืนNoneหากไม่มีอยู่ อาร์กิวเมนต์ที่สองซึ่งเป็นทางเลือกสามารถระบุค่าดีฟอลต์อื่นได้

(หมายความว่าเช็คของคุณก็เป็นได้if getenv("FOO"))

คุณไม่ต้องการรับมันคุณต้องการตรวจสอบว่ามีอยู่จริงหรือไม่

ไม่ว่าจะด้วยวิธีใดก็ตามgetenvเป็นเพียงกระดาษห่อหุ้มenviron.getแต่คุณไม่เห็นคนที่ตรวจสอบการเป็นสมาชิกในการแมปด้วย:

from os import environ
if environ.get('Foo') is not None:

สรุปให้ใช้:

if "FOO" in os.environ:
    pass

ถ้าคุณเพียงต้องการตรวจสอบสำหรับการดำรงอยู่ในขณะที่การใช้งานgetenv("FOO")จริงหากคุณต้องการที่จะทำสิ่งที่มีค่าที่คุณอาจได้รับ


2
ขอบคุณสำหรับคำอธิบาย ฉันจะเก็บสิ่งนี้ไว้ในใจ
Kshitij Saraogi

29

มีกรณีสำหรับโซลูชันอย่างใดอย่างหนึ่งขึ้นอยู่กับสิ่งที่คุณต้องการทำตามเงื่อนไขกับการมีอยู่ของตัวแปรสภาพแวดล้อม

กรณีที่ 1

เมื่อคุณต้องการดำเนินการที่แตกต่างกันโดยอิงจากการมีอยู่ของตัวแปรสภาพแวดล้อมอย่างหมดจดโดยไม่สนใจมูลค่าของมันวิธีแก้ปัญหาแรกคือแนวทางปฏิบัติที่ดีที่สุด อธิบายอย่างรวบรัดสิ่งที่คุณทดสอบ: คือ 'FOO' ในรายการตัวแปรสภาพแวดล้อม

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

กรณีที่ 2

เมื่อคุณต้องการตั้งค่าเริ่มต้นหากไม่ได้กำหนดค่าในตัวแปรสภาพแวดล้อมโซลูชันที่สองมีประโยชน์จริงแม้ว่าจะไม่อยู่ในรูปแบบที่คุณเขียนไว้:

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

หรือบางที

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

โปรดทราบว่าหากคุณมีหลายตัวเลือกสำหรับแอปพลิเคชันของคุณคุณอาจต้องการตรวจสอบChainMapซึ่งจะช่วยให้สามารถรวมคำสั่งหลายรายการตามคีย์ได้ มีตัวอย่างนี้ในChainMapเอกสาร:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)

15

เพื่อความปลอดภัยในการใช้งาน

os.getenv('FOO') or 'bar'

กรณีมุมที่มีคำตอบข้างต้นคือเมื่อตั้งค่าตัวแปรสภาพแวดล้อม แต่ว่างเปล่า

สำหรับกรณีพิเศษนี้คุณจะได้รับ

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

หรือ

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

เพื่อหลีกเลี่ยงสิ่งนี้ให้ใช้ or

os.getenv('FOO') or 'bar'

แล้วคุณจะได้รับ

print(os.getenv('FOO') or 'bar')
# bar

เมื่อใดที่เรามีตัวแปรสภาพแวดล้อมว่าง

คุณลืมกำหนดค่าใน.envไฟล์

# .env
FOO=

หรือส่งออกเป็น

$ export FOO=

หรือลืมตั้งค่า settings.py

# settings.py
os.environ['FOO'] = ''

อัปเดต:หากมีข้อสงสัยโปรดดูหนึ่งบรรทัดเหล่านี้

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"

ลายเซ็นสำหรับ getenv เป็นdef getenv(key, default=None):เช่นนั้นหากเป็นเช่นนั้นควรอนุญาตให้ใช้ค่าเริ่มต้นเทียบกับหรือไวยากรณ์ในตอนเริ่มต้น
Chris McKee

@Chris McKee ลองสิ่งนี้>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))
Levon

ลายเซ็นวิธีทำให้เข้าใจผิด😜
Chris McKee

1
@Chris McKee อีกตัวอย่างหนึ่ง$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon

3

ในกรณีที่คุณต้องการตรวจสอบว่าไม่ได้ตั้งค่าตัวแปร env หลายตัวคุณสามารถดำเนินการดังต่อไปนี้:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))

-1

ความคิดเห็นของฉันอาจไม่เกี่ยวข้องกับแท็กที่ให้มา อย่างไรก็ตามฉันถูกนำไปที่หน้านี้จากการค้นหาของฉัน ฉันกำลังมองหาการตรวจสอบที่คล้ายกันใน R และฉันได้สิ่งต่อไปนี้ด้วยความช่วยเหลือของโพสต์ @hugovdbeg ฉันหวังว่ามันจะเป็นประโยชน์สำหรับคนที่กำลังมองหาวิธีแก้ปัญหาที่คล้ายกันใน R

'USERNAME' %in% names(Sys.getenv())
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.