2009-12-16 11 views
24

मुझे गतिशील रूप से एक पर्ल मॉड्यूल शामिल करने की आवश्यकता है, लेकिन यदि संभव हो तो कार्य कोडिंग मानकों के कारण eval से दूर रहना चाहेंगे। यह काम करता है:मैं eval उपयोग किए बिना गतिशील रूप से पर्ल मॉड्यूल कैसे शामिल कर सकते हैं?

$module = "My::module"; 
eval("use $module;"); 

लेकिन मैं eval बिना यह करने के लिए यदि संभव हो तो एक तरह से की जरूरत है। सभी Google खोज eval विधि का कारण बनती हैं, लेकिन किसी भी अन्य तरीके से नहीं।

क्या eval के बिना ऐसा करना संभव है?

+1

डुप्लिकेट:। http://stackoverflow.com/questions/442710/how-do-i-use-a-perl-package-known-only-in-runtime –

+0

इस बारे में खेद है कि मैं लेकिन नहीं कर सके खोजे गए ' कुछ भी नहीं मिला। – user226723

+2

मुझे आपके कोडिंग मानकों को अपडेट किया जाएगा। मूल रूप से हार्ड कोड वाले eval'ing के बारे में कुछ भी गलत या असुरक्षित नहीं है स्ट्रिंग। आप जो चाहते हैं उसे पूरा करने का यह सबसे आसान तरीका है। यदि आप उपयोगकर्ता इनपुट में गुजर रहे हैं, तो यह एक और कहानी है ... – runrig

उत्तर

43

रनटाइम पर मॉड्यूल लोड करने के लिए require का उपयोग करें। यदि मॉड्यूल लोड नहीं किया जा सकता है तो यह अक्सर एक ब्लॉक (स्ट्रिंग नहीं) eval में लपेटने का एक अच्छा विचार है।

eval { 
    require My::Module; 
    My::Module->import(); 
    1; 
} or do { 
    my $error = [email protected]; 
    # Module load failed. You could recover, try loading 
    # an alternate module, die with $error... 
    # whatever's appropriate 
}; 

eval {...} or do {...} वाक्य रचना और [email protected] की एक प्रति लेने के लिए कारण है क्योंकि [email protected] एक वैश्विक चर कई अलग अलग चीजों से सेट किया जा सकता है कि है। आप दौड़ की स्थिति से बचने के लिए यथासंभव यथासंभव मूल्य को पकड़ना चाहते हैं, जहां किसी और ने इसे एक अलग मूल्य पर सेट किया है।

आप क्रम जब तक मॉड्यूल का नाम पता नहीं है, तो आप मॉड्यूल का नाम बीच अनुवाद (मेरे :: मॉड्यूल) और फ़ाइल नाम (मेरे/Module.pm) मैन्युअल रूप से करना होगा:

my $module = 'My::Module'; 

eval { 
    (my $file = $module) =~ s|::|/|g; 
    require $file . '.pm'; 
    $module->import(); 
    1; 
} or do { 
    my $error = [email protected]; 
    # ... 
}; 
+0

हम्म। यह अच्छा है क्योंकि आप आवश्यकता को एक eval में लपेटते हैं, लेकिन आपकी आवश्यकता विशेष रूप से गतिशील नहीं है। अगर कोई जवाब विलय कर सकता है, तो दान और आपका टॉप उम्मीदवार होगा। – innaM

+0

जबकि उसकी आवश्यकता गतिशील नहीं थी, मैं इसे आसानी से बनाने में सक्षम था (जैसा कि पिकार्ड कहता है)। उत्तर के लिए धन्यवाद! – user226723

+0

यह बहुत थ्रेडसेफ नहीं है, उदा। http://www.perlfoundation.org/perl5/index.cgi?exception_handling – Ether

10

ठीक है, वहाँ हमेशा require में

require 'My/Module.pm'; 
My::Module->import(); 

नोट के रूप में आप खो देते हैं कि जो कुछ भी प्रभाव आप संकलन समय के बजाय कार्यावधि में बुलाया जा रहा है import से मिल गया है सकता है।

संपादित करें: इस और eval तरीके के बीच ट्रेडऑफ हैं: eval आपको सामान्य मॉड्यूल सिंटैक्स का उपयोग करने देता है और मॉड्यूल नाम अमान्य होने पर आपको एक और स्पष्ट त्रुटि देता है (जैसा कि केवल नहीं मिला है)। ओटीओएच, eval रास्ता (संभावित रूप से) मनमाना कोड इंजेक्शन के लिए अधिक विषय है।

+0

उत्तर के लिए धन्यवाद। मैंने आपको वोट दिया क्योंकि मैं दोनों उत्तरों का चयन नहीं कर सकता :)। – user226723

4

नहीं, यह नहीं करने के लिए संभव eval बिना, के रूप में require() bareword मॉड्यूल नाम की आवश्यकता है perldoc -f require पर वर्णन किए गए है,। हालांकि, यह eval का बुरा उपयोग नहीं है, क्योंकि यह मनमाने ढंग से कोड के इंजेक्शन की अनुमति नहीं देता है (मान लीजिए कि आपके पास require आईएनजी फ़ाइल की सामग्री पर नियंत्रण है)।

संपादित करें: कोड नीचे संशोधित है, लेकिन मैं पूर्ण संस्करण के लिए पहला संस्करण छोड़ रहा हूं।

मैं मैं इस छोटे से चीनी मॉड्यूल का उपयोग करने के क्रम में गतिशील लोड करते थे का उपयोग करें:

package MyApp::Util::RequireClass; 

use strict; 
use warnings; 

use Exporter 'import'; # gives you Exporter's import() method directly 
our @EXPORT_OK = qw(requireClass); 

# Usage: requireClass(moduleName); 
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports); 
sub requireClass 
{ 
    my ($class) = @_; 
    eval "require $class" or do { die "Ack, can't load $class: [email protected]" }; 
} 

1; 

पी एस। मैं इस परिभाषा पर देख रहा हूं (मैंने इसे थोड़ी देर पहले लिखा था) और मैं इसे जोड़ने में सोच रहा हूं: $class->export_to_level(1, undef, @imports); ... यह काम करना चाहिए, लेकिन परीक्षण नहीं किया गया है।

संपादित: संस्करण 2 अब एक eval के बिना बहुत अच्छे (धन्यवाद ysth): http://metacpan.org/pod/Class::MOP

+3

"आवश्यकता() को शब्दकोष मॉड्यूल नाम की आवश्यकता है" - नहीं, यह नहीं करता है; बस एस # :: #/# जी; और पथनाम प्राप्त करने के लिए '.pm' संलग्न करें। – ysth

+0

@ysth: वाह, आप सही हैं ... दस्तावेज़ इस बारे में बहुत अस्पष्ट हैं लेकिन यह वास्तव में काम करता है। वैसे यह शानदार है, अब मैं उस बुराई eval को खत्म करने के लिए अपने मॉड्यूल संशोधित कर सकते हैं :) – Ether

1

कक्षा :: CPAN पर एमओपी इस के लिए एक load_class विधि है कैसे अपने उदाहरण के साथ कोर मॉड्यूल Module::Load

उपयोग के बारे में:

use Module::Load; 
my $module = "My::module"; 
load $module; 

-

"मॉड्यूल :: लोड क्रम दोनों मॉड्यूल और फ़ाइलों की आवश्यकता होती है" "लोड जानना आवश्यक है कि आप या तो एक फ़ाइल या एक मॉड्यूल की आवश्यकता के लिए कोशिश कर रहे हैं की आवश्यकता समाप्त।"

यह विफल रहता है यह कैसा की कुछ के साथ मर जाएगा तो "@INC में xxx का पता लगाने कर सकते हैं नहीं (@INC शामिल हैं: ..."।

16

: :)

package MyApp::Util::RequireClass; 

use strict; 
use warnings; 

use Exporter 'import'; # gives you Exporter's import() method directly 
our @EXPORT_OK = qw(requireClass); 

# Usage: requireClass(moduleName); 
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports); 
sub requireClass 
{ 
    my ($class) = @_; 

    (my $file = $class) =~ s|::|/|g; 
    $file .= '.pm'; 
    require $file; # will die if there was an error 
} 

1; 
+1

यह एक कोर मॉड्यूल है, तो इस्तेमाल किया जाना चाहिए। – alexk

0

मैं जैसी चीजों करना पसंद ..

require Win32::Console::ANSI if ($^O eq "MSWin32");

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^