2011-07-13 13 views
30

Chcę zaimportować pakiet w zależności od wybranej przez użytkownika wartości.

Domyślnie jest file1.py:

from files import file1 

Jeśli użytkownik wybierze file2, powinno być:

from files import file2 

W PHP można to zrobić za pomocą variable variables:

$file_name = 'file1'; 
include($$file_name); 
$file_name = 'file2'; 
include($$file_name); 

Jak mogę to zrobić w Pythonie?

+1

Nie rób tego! Używanie danych wejściowych zwykle nie jest godne zaufania, a oślepienie oceny kodu na podstawie tego jest złym pomysłem. –

+0

dziękuję, używam domyślnego zestawu do zaimportowania teraz. – skargor

Odpowiedz

43

Python nie posiada funkcję, która znajduje się bezpośrednio odpowiednik "zmiennych zmiennych" PHP. Aby uzyskać wartość "zmiennej zmiennej" (lub wartość dowolnego innego wyrażenia), można użyć funkcji eval.

foo = "Hello World" 
print eval("foo") 

Jednak nie można tego użyć w oświadczeniu import.

Możliwe jest użycie funkcji __import__ do importowania za pomocą zmiennej.

package = "os" 
name = "path" 

imported = getattr(__import__(package, fromlist=[name]), name) 

jest równoważna

from os import path as imported 
26

Jak Fredrik Lundh states:

W każdym razie, oto jak te oświadczenia i funkcje działają:

import X importuje moduł X i tworzy odniesienie do tego modułu w bieżącym obszarze nazw. Albo innymi słowy, po tym, jak uruchomić ten oświadczenie, można użyć X.name odnosić się do rzeczy określonej w module X.

from X import * importuje moduł X i tworzy referencje w bieżącym obszarze nazw w do wszystkich obiektów publicznych określonych przez ten moduł (że jest, wszystko, co nie ma nazwy zaczynającej się na "_"). Innymi słowy, po uruchomieniu tego polecenia można po prostu użyć zwykłej nazwy , aby odnieść się do rzeczy zdefiniowanych w module X. Ale samo X nie jest zdefiniowane jako , więc X.name nie działa. A jeśli nazwa została już zdefiniowana, to jest zastępowana przez nową wersję. A jeśli nazwa w X zostanie zmieniona na punkt na inny obiekt, moduł nie zauważy.

importuje moduł X i tworzy odniesienia w bieżącym obszarze nazw do podanych obiektów. Innymi słowy, możesz teraz używać teraz w swoich programach a i b i c.

Wreszcie X = __import__(‘X’) działa jak import X, z tą różnicą, że 1) podać nazwę modułu jako ciąg znaków, a 2) jednoznacznie przypisać go do zmiennej w bieżącej przestrzeni nazw. .

A tak przy okazji, że jest ostatni sposób, że jesteś zainteresowany w

Wystarczy napisać (na przykład):

var = "datetime" 
module = __import__(var) 
+0

Dziękuję za jasną i wyczerpującą odpowiedź. – DrBailey

4

To chyba bardzo zły pomysł, aby użytkownik mógł wybrać to, co do importu. Pakiety mogą uruchamiać kod podczas importu, więc skutecznie pozwalasz użytkownikowi na dowolne wykonanie kodu w twoim systemie! Znacznie bezpieczniej jest robić coś jak

if user_input == 'file1.py': 
    from files import file1 as file 
elif user_input == 'file2.py': 
    from files import file2 as file 
else: 
    file = None 
    print "Sorry, you can't import that file" 
33

Starego wątku, ale potrzebowałem odpowiedzi, więc może jeszcze ktoś inny ...

Jest czystszy sposób to zrobić w Pythonie 2.7+:

import importlib 


my_module = importlib.import_module("package.path.%s" % module_name) 
+0

Wskazówka: będziesz potrzebować pakietu 'package.path .__ init __. Py' dla [import to work] (http://stackoverflow.com/a/1260813/673991). –

2

Opierając się na mattjbray „s odpowiedź:

from importlib import import_module 

# lookup in a set is in constant time 
safe_names = {"file1.py", "file2.py", "file3.py", ...} 

user_input = ... 

if user_input in safe_names: 
    file = import_module(user_input) 
else: 
    print("Nope, not doing this.") 

oszczędza kilka linijek kodu i pozwala można programowo ustawić safe_names lub załadować kilka modułów i przypisać je do dyktatury, na przykład.

Powiązane problemy