Python'da mevcut modülün özniteliklerine bir başvuru nasıl alınır


119

Yapmaya çalıştığım şey komut satırında şöyle görünecek:

>>> import mymodule
>>> names = dir(mymodule)

Kendi mymoduleiçinde tanımlanan tüm isimlere nasıl referans alabilirim mymodule?

Bunun gibi bir şey:

# mymodule.py
names = dir(__thismodule__)

Yanıtlar:


135

Yalnızca globalleri kullanın ()

globals () - Geçerli genel sembol tablosunu temsil eden bir sözlük döndürür. Bu her zaman geçerli modülün sözlüğüdür (bir işlev veya yöntem içinde bu, çağrıldığı modül değil, tanımlandığı modüldür).

http://docs.python.org/library/functions.html#globals


4
Tanımlayıcı modül yerine çağıran modülün gloaballerine () erişmenin herhangi bir yolu var mı?
dimo414

9
Arayanın globallerini geri izleme modülünden ( docs.python.org/library/traceback.html ) almayı deneyebilirsiniz , ancak bu karanlık büyü bölgesine giriyor. Ne yapmaya çalıştığını bilmiyorum ama buna ihtiyacın olursa tasarımını yeniden düşünmek isteyebilirsin.
Maciej Pasternacki

Klasik bir "X'e ihtiyacım var (Y'yi bitirmek için) -> X'e ihtiyacınız yok, Z'ye ihtiyacınız var". Yine de X'e ihtiyacım var! Alınma, sadece bunu eğlenceli buluyorum ve en çok oylanan cevap bana ihtiyacım olan cevabı veriyor :)
Pawamoy

Globals () 'ın çağrıldığı bağlama bağlı olduğundan yanlış sonuç döndürebileceğini unutmamak önemlidir. Örneğin, bir sınıf işlevinden bir çağrı yaparsanız, o zaman önemli ölçüde farklı olan geçerli modül bağlamını değil, sınıfa bağlı genel bağlamı döndürür. Ücretsiz bir işlevden arama yapsanız bile, işlevin nasıl içe aktarıldığına bağlı olarak farklı bir modül genel içeriği döndürebilir.
Andry

163

Daha önce bahsedildiği gibi, globals size modülde tanımlanan isimlerin bir listesini veren dir () yerine size bir sözlük verir. Genelde bunun yapıldığını görüyorum:

import sys
dir(sys.modules[__name__])

2
Bunun ' ana ' modül (terminalde çalışan modülün adıdır) için işe yaramayacağına dair bir yorum ekleyecektim , çünkü bu sys.modules'te listelenmiyor gibi görünüyor - ama gerçekten çalışıyor :)
markm

Ancak, ipdb'den çalışmıyor gibi görünüyor (dosyanıza "import ipdb; ipdb.set_trace ()" ekleyin).
gatoatigrado

9
Mükemmel! Bu sadece mevcut modülün docstringini bir kullanım mesajı olarak kullanmama izin verdi - sys.modules[__name__].__doc__.
george

Ve süper hilekâr olmak için. operators.attrgetter('module.attribute')(sys.modules[__name__])- bilirsiniz, eğer çılgınca şeyler yaparsanız, insanların dizelerden dinamik olarak paketler içe aktarmamanızı söylediği çılgınca şeyler yaparsanız ve sonra bir sınıfta ya da başka bir şey olmadan bunları maymun yamalar ...
casey

2
George tarafından yapılan açıklamayı okuyan herkes için: sys.modules[__name__].__doc__== __doc__bu geçerli isim alanında tanımlandığı gibi. Modül nesnesini kendi özniteliklerine erişmek için getirmek bu nedenle gerekli değildir.
Oliver Bestwalter

1

Cevap vermek için geç olabilir ama kendim için doğru cevabı bulamadım. Python'daki en yakın ve kesin çözüm (daha hızlı inspect.stack()) 3.7.x:

  # search for first module in the stack
  stack_frame = inspect.currentframe()
  while stack_frame:
    print('***', stack_frame.f_code.co_name, stack_frame.f_code.co_filename, stack_frame.f_lineno)
    if stack_frame.f_code.co_name == '<module>':
      if stack_frame.f_code.co_filename != '<stdin>':
        caller_module = inspect.getmodule(stack_frame)
      else:
        # piped or interactive import
        caller_module = sys.modules['__main__']
      if not caller_module is None:
        #... do something here ...
      break
    stack_frame = stack_frame.f_back

Artıları :

  • Yöntemden daha hassas globals().
  • Örneğin, kancalama yoluyla veya aşağıdaki gibi 3bparty araçlarıyla eklenebilen yığın ara çerçevelerine bağlı değildir pytest:
*** foo ... ..
*** boo ... ..
*** runtest c:\python\x86\37\lib\site-packages\xonsh\pytest_plugin.py 58
*** pytest_runtest_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 125
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** <lambda> c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** from_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 229
*** call_runtest_hook c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** call_and_report c:\python\x86\37\lib\site-packages\_pytest\runner.py 176
*** runtestprotocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 95
*** pytest_runtest_protocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 80
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** pytest_runtestloop c:\python\x86\37\lib\site-packages\_pytest\main.py 258
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** _main c:\python\x86\37\lib\site-packages\_pytest\main.py 237
*** wrap_session c:\python\x86\37\lib\site-packages\_pytest\main.py 193
*** pytest_cmdline_main c:\python\x86\37\lib\site-packages\_pytest\main.py 230
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** main c:\python\x86\37\lib\site-packages\_pytest\config\__init__.py 90
*** <module> c:\Python\x86\37\Scripts\pytest.exe\__main__.py 7
  • Python borulu veya etkileşimli oturumu yönetebilir.

Eksileri:

  • Bir tür çok hassas ve pytest.exeistediğiniz gibi olmayan bir yürütülebilir dosyada kayıtlı modülleri döndürebilir .
  • inspect.getmodule yine de kancaya bağlı olarak geçerli modüllerde Yok döndürebilir

Python için bir uzantım var: Tam yol verildiğinde bir modül nasıl içe aktarılır?

Bu durum için sarmalayıcı işlevlerine sahip uzantı:

def tkl_get_stack_frame_module_by_offset(skip_stack_frames = 0, use_last_frame_on_out_of_stack = False):
  ...

def tkl_get_stack_frame_module_by_name(name = '<module>'):
  ...

Uzantıyı doğru şekilde başlatmanız gerekir:

# portable import to the global space
sys.path.append(<path-to-tacklelib-module-directory>)
import tacklelib as tkl

tkl.tkl_init(tkl, global_config = {'log_import_module':os.environ.get('TACKLELIB_LOG_IMPORT_MODULE')})

# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()

# use `tkl_*` functions directly from here ...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.