2017-05-28 85 views
-1

我想檢查一個字符串 - 它是一個導入命令嗎?我試過Python 3:檢查一個字符串是否是導入命令

# Helper - analyses a string - is it an import string? 
""" 
fromlike - from foo import bar 
classic - import foo 
classic_as - import foo as baz 
""" 
def check_is_import(string): 
    importname = '' 
    fromlike = False 
    classic = False 
    classic_as = False 
    if string[0:4] is 'from': 
     fromlike = True 
     importname = '' 
    if not fromlike and (string[0:6] is 'import'): 
     classic = True 
     importname = string.split(' ')[1] 
    if classic: 
     commandlist = string.split(' ') 
     if commandlist[2] is 'as': 
      classic_as = True 
      importname = commandlist[3] 
      del commandlist 
    if fromlike: 
     return ('fromlike', importname) 
    elif classic and (not classic_as): 
     return ('classic', importname) 
    elif classic_as: 
     return ('classic_as', importname) 
    else: 
     return ('no_import', importname) 

但它適用於「fromlike」進口。 (注意:我不是問「爲什麼這個代碼不工作?」,我只是在尋找一個解決方案)什麼代碼肯定會檢測到所有的導入?基本上我的代碼需要一部分字符串。如果[0:4]切片等於'from',則該字符串是「fromlike import」。否則:如果[0:6]切片等於'import',則該字符串是「經典導入」。如果它檢測到'as',它會找到僞名。此函數必須返回包含索引0下的導入類型和索引1下導入的模塊名稱的元組。

+1

爲什麼有一隻狗,何必自己嗎?使用['ast.parse()'](https://docs.python.org/3/library/ast.html#ast.parse)並查看生成的AST樹。 –

+0

@MartijinPieters請給我一個例子。 –

+0

在編寫答案的過程中。 :-) –

回答

2

如果要確保處理所有Python導入窗體,請讓Python執行解析。使用ast.parse() function並使用生成的分析樹;你要麼得到ImportImportFrom對象:

| Import(alias* names) 
    | ImportFrom(identifier? module, alias* names, int? level) 

每個alias由名稱及其用於導入名字可選標識符

-- import name with optional 'as' alias. 
alias = (identifier name, identifier? asname) 

注意,可以有多個進口!您可以導入classicfromlike,並且都可以導入多個名稱。你的函數需要返回一個列表(type, name)元組。對於無效輸入,拋出一個異常(ValueError是一個不錯的選擇此處):

import ast 

def check_is_import(string): 
    try: 
     body = ast.parse(string).body 
    except SyntaxError: 
     # not valid Python 
     raise ValueError('No import found') 
    if len(body) > 1: 
     # not a single statement 
     raise ValueError('Multiple statements found') 
    if not isinstance(body[0], (ast.Import, ast.ImportFrom)): 
     raise ValueError('No import found') 
    type_ = 'classic' if isinstance(body[0], ast.Import) else 'fromlike' 
    results = [] 
    for alias in body[0].names: 
     alias_type = type_ 
     if alias.asname: 
      alias_type += '_as' 
     results.append((alias_type, alias.asname or alias.name)) 
    return results 

的方法或許應該改名爲extract_import_names(),因爲這反映了它要好得多。

演示:

>>> check_is_import('from foo import bar') 
[('fromlike', 'bar')] 
>>> check_is_import('import foo') 
[('classic', 'foo')] 
>>> check_is_import('import foo as baz') 
[('classic_as', 'baz')] 
>>> check_is_import('from foo import bar, baz as spam, monty as python') 
[('fromlike', 'bar'), ('fromlike_as', 'spam'), ('fromlike_as', 'python')] 
>>> check_is_import('import foo as baz, baz, spam as ham') 
[('classic_as', 'baz'), ('classic', 'baz'), ('classic_as', 'ham')] 
>>> check_is_import('invalid python') 
Traceback (most recent call last): 
    File "<stdin>", line 3, in check_is_import 
    File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/ast.py", line 35, in parse 
    return compile(source, filename, mode, PyCF_ONLY_AST) 
    File "<unknown>", line 1 
    invalid python 
       ^
SyntaxError: invalid syntax 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 6, in check_is_import 
ValueError: No import found 
>>> check_is_import('import foo; import bar') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 9, in check_is_import 
ValueError: Multiple statements found 
>>> check_is_import('1 + 1 == 2') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 11, in check_is_import 
ValueError: No import found 
+0

錯誤!在問題中解釋。 –

+0

@VladislavToncharov:很久以前已經糾正。 –

相關問題