Pythonの構文エラーについて

Pythonの一般的な構文エラーとその解決策について説明します。エラー発生防止のための事前戦略と、発生した場合に効率的に解決するための事後対応について学びましょう。
5 min read
Python Syntax Errors Explained blog image

どの言語にも、有効な構成方法を定義する規則があります。これを言語の構文と呼びます。コーディングについて学び始めたばかりのユーザーにとって、構文エラーへの対処は避けては通れぬ道となります。初心者が構文規則を理解するのに苦労し、誤字や記号の配置ミスを経験することは非常に一般的です。

コーディングの過程においてすべてのユーザーが経験する構文エラーですが、原因を理解するのが早ければ早いほど、迅速な解決が可能となります。

この記事では、 Python におけるさまざまな構文エラーと、これらを回避する方法について学びます。

Pythonの構文エラー

どのプログラミング言語においても、構文規則に従わないと構文エラーが発生し、コードを実行できなくなる可能性が高まります。

Pythonでは、 Pythonインタプリタ がPythonコードの読み取りと実行を行い、高レベルのPythonと、ユーザーのコンピューターが理解できる低レベルの機械語の間の翻訳者として機能します。ユーザーのコードがPythonの構文規則に従わない場合、インタプリタはコードを処理することができません。

Pythonインタプリタは構文エラーに遭遇すると、一時停止してエラーメッセージを表示します。このメッセージには、エラーの原因となったコード行へのトレースバックと、最も早くエラーが検出された行の場所を示すインジケーターが含まれています。

インタプリタは、問題の診断と解決に役立つ関連情報をできるだけ多く提供しようとするため、エラーメッセージをよく読むことが重要となります。

Pythonの構文エラーはすべて構造に関するものであり、コマンドが言語の文法規則に反している場合に発生します。例として、英語で書く文章は常に大文字で始め、句読点で終わらせる必要があります。同様に、Pythonでは文末には必ず改行を行い、コードブロックを付けて( if 文やループのように)正しくインデントする必要があります。

 ランタイムエラーに精通しているユーザーは、構文エラーがこれらとどう違うのか疑問に思うかもしれません。構文エラーは、発生するとプログラムの実行が妨げられます。ランタイムエラーの場合、プログラムの実行開始後に発生する点が大きな違いとなります。

さまざまな種類の構文エラーの検証

Pythonにはさまざまな 構文規則があるため、構文エラーの発生原因も多数あります。このセクションでは、いくつかの一般的なエラーと解決策について学ぶことができます。

句読点の配置ミスや欠落、または不一致

Pythonは、コードの構造を理解するためにさまざまな句読点を使用します。構文エラーの発生を避けるには、句読点のそれぞれが正しく配置され、対応する別の句読点と正確に一致していることを確認する必要があります。

例として、丸括弧(())、角括弧([])、波括弧({})は、常にペアで使用する必要があります。これは、これらの句読点を開いた場合、必ず閉じる必要があることを意味します。

次の例では、オブジェクトを定義するために使用されている波括弧が閉じられていません。

# Incorrect
proxies = {
    'http': proxy_url,
    'https': proxy_url

これを実行しようとすると、インタプリタは SyntaxErrorを表示します。

File "python-syntax-errors.py", line 2
    proxies = {
            ^
SyntaxError: '{' was never closed

前述のように通常、Pythonインタプリタは詳細なエラーメッセージを表示します。ここでは、エラーが発生したファイル名と行番号、およびコード内のエラーが検出された場所を示す矢印が表示されています。また、 「{」が閉じられていないことも説明されています。

これらの情報により、問題を解決するには波括弧を閉じる必要がある、という結論に難なく達することができます。

# Correct
proxies = {
    'http': proxy_url,
    'https': proxy_url
} # Closed a curly bracket

エラーの原因となることが多い句読点の例として、引用符(「’」または「”」)も挙げることができます。他の多くのプログラミング言語と同様に、Pythonも引用符を使用して文字列を定義します。文字列を開いたり閉じたりするには、同じ種類の引用符を使用する必要があります。

# Incorrect
host = "brd.superproxy.io'

一重引用符と二重引用符が混在していると、構文エラーが発生します。

File "python-syntax-errors.py", line 2
    host = "brd.superproxy.io'
        ^
SyntaxError: unterminated string literal (detected at line 2)

ここで、インタプリタは2行目の文字列リテラルが終了していないことを説明しています。

# Correct
host = "brd.superproxy.io"

一重引用符を1ペア使用することによっても必要な結果が得られます。

1つの文字列で、一重引用符と二重引用符を両方使用する必要がある場合もあります。このような場合は、次のように三重引用符を使用することができます。

quote = """He said, "It's the best proxy service you can find!", and showed me this provider."""

Pythonでは、カンマはリストやタプル、引数の項目を区切るために使用されます。カンマの欠落は、予期せぬ結果を招く場合があります。

# Incorrect
proxies= [
    {"http": "http://123.456.789.1:8080", "https": "https://123.456.789.1:8080"}
    {"http": "http://98.765.432.1:3128", "https": "https://98.765.432.1:3128"}
    {"http": "http://192.168.1.1:8080", "https": "https://192.168.1.1:8080"}
]

このコードを実行すると、次のエラーメッセージが表示されます。

File "python-syntax-errors.py", line 3
{"http": "http://123.456.789.1:8080", "https": "https://123.456.789.1:8080"}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

エラーメッセージはできる限り役に立つように作成されていますが、提示される解決策が必ずしも正確であるとは限りません。このスニペットでは4つのカンマが欠落していますが、エラーメッセージでは最初の欠落分のみが取り上げられています。問題を解決するには、エラーメッセージの周辺のコードを確認し、カンマが欠落している可能性のある他の場所を探します。

# Correct
proxies = [
    {"http": "http://123.456.789.1:8080", "https": "https://123.456.789.1:8080"},
    {"http": "http://98.765.432.1:3128", "https": "https://98.765.432.1:3128"},
    {"http": "http://192.168.1.1:8080", "https": "https://192.168.1.1:8080"}
]

カンマとは反対に、新しいコードブロックを開始するにはコロンを使用( if 文や for ループと同様に)します。

import requests
from bs4 import BeautifulSoup

# Incorrect
response = requests.get('https://example.com')
if response.status_code == 200
    soup = BeautifulSoup(response.content, 'html.parser')
    title = soup.title.text
    print(title)
)

コロンが欠落していると、次の構文エラーが発生します。

if response.status_code == 200
    ^
SyntaxError: expected ':'   

このエラーメッセージからコロンがないことが簡単にわかるため、推奨される場所にコロンを追加することにより、問題を解決することができます。

import requests
from bs4 import BeautifulSoup

# Correct
response = requests.get('https://example.com')
if response.status_code == 200:
    soup = BeautifulSoup(response.content, 'html.parser')
    title = soup.title.text
    print(title)

Pythonキーワードのスペルおよび配置ミス、または欠落

Pythonキーワード は特定の意義と用途に限定された特別な単語であり、変数名として使用することはできません。キーワードのスペルや配置場所を間違えたり、配置し忘れたりすると、インタプリタがエラーを表示します。

例として、 requests や pprint のモジュールをWebスクレイピングプロジェクトにインポートする際、 import キーワードのスペルを間違えたとします。

# Incorrect
improt requests
import pprint

このスペルミスにより、インタプリタは次のような invalid syntax(無効な構文) エラーを表示します。

File "python-syntax-errors.py", line 2
    improt requests
        ^^^^^^^^
SyntaxError: invalid syntax

残念ながら、このエラーメッセージの意味は明確ではないため、問題の原因を突き止めるには調査が必要となります。エラーメッセージの矢印が requestsを指しているのがわかります。これが、インタプリタが最初に構文エラーを検出した場所になります。モジュール名のスペルを間違えても構文エラーは発生しないため、原因として唯一考えられるのは import キーワードのスペルミスになります。

 import という単語の修正により、簡単にエラーが解決します。

# Correct
import requests
import pprint

次のように、 from ... import ... の文の構成を間違える可能性も考えられます。

import BeautifulSoup from bs4

一見問題ないように見えますが、 from キーワードは importの前に配置する必要があるため、上記のコードを実行した場合にはエラーが発生します。

File "python-syntax-errors.py", line 2
import BeautifulSoup from bs4
    ^^^^
SyntaxError: invalid syntax

 from と import を入れ替えることにより、問題は解決します。

from bs4 import BeautifulSoup

また、Pythonでのコーディングの際に発生することが予想される問題として、キーワードの欠落も挙げることができます。キーワードの欠落はさまざまなPythonエラーの原因となるため、前述した他のエラーよりもやや扱いにくい部分があります。

値を返すべき関数に return キーワードを含めるのを忘れると、関数は予想どおりに動作しません。

def fetch_data():
    response = requests.get('https://example.com')
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    # Missing a return statement here
    
data = fetch_data()

構文エラーは発生しませんが、関数は想定された結果ではなく None を返します。 return キーワードを追加することにより、前述のコードが修正されます。

def fetch_data():
    response = requests.get('https://example.com')
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    return data

data = fetch_data()

関数の定義時に def キーワードを忘れると、構文エラーが発生します。

# Missing the `def` keyword
fetch_data():
    response = requests.get('https://example.com')
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    return data

data = fetch_data()

インタプリタは、関数名の前にキーワードが配置されていることを想定しているため、上記のコードでは構文エラーを表示します。

File "python-syntax-errors.py", line 1
   fetch_data():
               ^
SyntaxError: invalid syntax

このため、 def キーワードを追加することによりエラーが解決します。

def fetch_data():
    response = requests.get('https://example.com')
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    return data

data = fetch_data()

条件文で if キーワードを忘れた場合、インタプリタは条件の前にキーワードが配置されていることを想定しているため、エラーを表示します。

import requests
from bs4 import BeautifulSoup

response = requests.get('https://example.com')
# Missing the if keyword
response.status_code == 200:
    soup = BeautifulSoup(response.content, 'html.parser')
    title = soup.title.text
    print(title)
File "python-syntax-errors.py", line 6
   response.status_code == 200:
                              ^
SyntaxError: invalid syntax

 if キーワードを含めさえすれば、この問題は解決します。

import requests
from bs4 import BeautifulSoup

response = requests.get('https://example.com')
if response.status_code == 200:
    soup = BeautifulSoup(response.content, 'html.parser')
    title = soup.title.text
    print(title)

これらは、Pythonにおけるキーワードの欠落により発生するエラーのほんのいくつかの事例です。キーワードの欠落は、他のエラーの原因となる可能性もあるため、十分な注意が必要です。

代入演算子の誤った使い方

Pythonでは、 代入に = シンボルが使用され、 比較には == が使用されます。これら2つの記号を混同することにより、構文エラーが発生する場合があります。

import requests
from bs4 import BeautifulSoup

# Incorrect
response = requests.get('https://example.com', proxies=proxies)
if response = requests.get('https://example.com/data', proxies=proxies):
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    for item in data:
    print(item.text)
else:
    print("Failed to retrieve data")

前のコードでは、インタプリタは問題の原因を正しく検出しています。

File "python-syntax-errors.py", line 5
if response = requests.get('https://example.com/data', proxies=proxies)
     ^^^^^^

この事例では、ユーザーは自分のレスポンスが request.get() メソッドへのレスポンスと同じであることを確認しようとしています。これは、 if 文の代入演算子を比較演算子に置き換える必要があることを意味しています。

import requests
from bs4 import BeautifulSoup

# Correct
response = requests.get('https://example.com', proxies=proxies)
# Change in the following line
if response == requests.get('https://example.com/data', proxies=proxies):
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    for item in data:
    print(item.text)
else:
    print("Failed to retrieve data")

インデントエラー

Pythonは、インデントを使用してコードブロックを定義します。コードが正しくインデントされていない場合、インタプリタはコードブロックの内容を区別できず、 IndentationError(インデントエラー)を表示します。

# Incorrect
async with async_playwright() as playwright:
await run(playwright)

前のコードからわかるように、ブロック(コロン)の定義の後にインデントがないため、これを実行した場合には次のエラーメッセージが表示されます。

File "python-syntax-errors.py", line 2
    await run(playwright)
    ^
IndentationError: expected an indented block after the with statement on line 1

この問題を解決するには、Pythonの構文規則に従い、コードブロックを正しくインデントします。

# Correct
async with async_playwright() as playwright:
    await run(playwright)

変数宣言における問題

Pythonの変数名は、文字またはアンダースコアで始める必要があり、使用できるのは文字と数字、そしてアンダースコアのみです。また、Pythonでは大文字と小文字が区別されるため、 myvariableと myVariable、および MYVARIABLE はすべて異なる変数となります。

変数名は、文字またはアンダースコア以外で始めることはできません。次の変数名は 1で始まるため、Pythonの構文規則に準拠していません。

# Incorrect
1st_port = 22225

このコードを実行すると、インタプリタは SyntaxError(構文エラー)を表示します。

File "python-syntax-errors.py", line 2
    1st_port = 1
    ^
SyntaxError: invalid decimal literal

これを解決するには、変数名が文字またはアンダースコアで始まるように変更を加える必要があります。次のオプションのどれでも使用することができます。

# Correct
first_port = 22225
port_no_1 = 22225

関数定義と呼び出しエラー

関数を定義するときは、 def キーワードを使用し、その後に関数名と括弧、そしてコロンを配置する必要があります。また、関数を呼び出すときは、関数名の後に括弧を配置する必要があります。これらの要素のいずれかを忘れると、構文エラーが発生します。

import requests
from bs4 import BeautifulSoup

# Incorrect
def fetch_data
response = requests.get('https://example.com')
soup = BeautifulSoup(response.content, 'html.parser')
data = soup.find_all('div', class_='data')
return data

# Incorrect
data = fetch_data

ここでは3つの要素が欠落しており、それぞれが個別の構文エラーを引き起こしています。これらのエラーを解決するには、関数名 fetch_dataの後に括弧とコロンを追加する必要があります。また、コードブロックの最後の行の関数呼び出しの後には、次のように括弧を追加する必要があります。

import requests
from bs4 import BeautifulSoup

# Corrected
def fetch_data():
    response = requests.get('https://example.com')
    soup = BeautifulSoup(response.content, 'html.parser')
    data = soup.find_all('div', class_='data')
    return data

# Corrected
data = fetch_data()

関数定義における括弧とコロンの欠落は、常に構文エラーを引き起こします。ただし、インタプリタは関数(fetch_data())の呼び出し時にユーザーが括弧を忘れたかどうかは認識しません。このような場合、必ずしも例外を投げるわけではないため、予期せぬ動作につながることがあります。

構文エラーを回避するためのベスト・プラクティス

エラーのないコードを書けるようになるまでには、たくさんの練習を要します。以下のベストプラクティスを理解して実装することで、一般的な構文エラーを回避することができます。

事前戦略

構文エラーに対処する最善の方法は、エラーの発生そのものを回避することです。

プロジェクトに取りかかる前に、コーディング言語の一般的な構文規則をよく理解しておく必要があります。

シンタックスハイライトとインデントチェック機能を備えたコードエディターを使用する

構文エラーを回避するためには、優れたコードエディターが最適なパートナーとなります。今日のコードエディターの大部分は、シンタックスハイライトやインデントチェックなどの機能を備えており、これらがコードの実行前にエラーを見つけるのに役立ちます。

例として、以下の図の if response.status_code == 200 行の末尾には、コロンがないためにエラーが発生したことを示す赤いマークが表示されています。

エラーが発生したことを示す赤いマーク

一貫したコーディングスタイルガイドラインに従う

何事でもそうであるように、クリーンでエラーのないコードを書くためにもやはり、一貫性が重要なポイントとなります。一貫したコーディングスタイルに従うことを目指しましょう。そうすることで、コードが読みやすく理解しやすくなり、エラーの発見と解決がより簡単になります。

Pythonでは、 PEP 8 スタイルガイド がコーディングスタイルの基準として広く認められています。これは、変数の命名やインデント、空白の使用などについてのガイドラインを提供しています。

小さく、明確に定義された関数でコードを書く

コードを小さく、明確に定義された関数に分割すると、管理とデバッグがより簡単になります。

各関数には、単一の明確な目的が必要となります。関数の実行すべき処理が多くなりすぎると、理解やデバッグが困難になる可能性があります。例として、次の scrape_and_analyze() 関数を見てみましょう。

import requests
from bs4 import BeautifulSoup
from textblob import TextBlob

def scrape_and_analyze():
    url = "https://example.com/articles"
    response = requests.get(url)
    soup = BeautifulSoup(response.content, "html.parser")
    titles = soup.find_all("h2", class_="article-title")
    sentiments = []
    for title in titles:
    title_text = title.get_text()
    blob = TextBlob(title_text)
    sentiment = blob.sentiment.polarity
    sentiments.append(sentiment)
    return sentiments

print(scrape_and_analyze())

この例における関数の場合、複数の小さな関数に分解し、その一つ一つがより小さく管理しやすいコードの部分を実行したほうが読みやすくなります。

import requests
from bs4 import BeautifulSoup
from textblob import TextBlob

def scrape_titles(url):
    """Scrape article titles from a given URL."""
    response = requests.get(url)
    soup = BeautifulSoup(response.content, "html.parser")
    titles = soup.find_all("h2", class_="article-title")
    return [title.get_text() for title in titles]

def analyze_sentiment(text):
    """Analyze sentiment of a given text."""
    blob = TextBlob(text)
    return blob.sentiment.polarity

def analyze_titles_sentiment(titles):
    """Analyze sentiment of a list of titles."""
    return [analyze_sentiment(title) for title in titles]

def scrape_and_analyze(url):
    """Scrape titles from a website and analyze their sentiment."""
    titles = scrape_titles(url)
    sentiments = analyze_titles_sentiment(titles)
    return sentiments

url = "https://example.com/articles"
print(scrape_and_analyze(url))

事後対応

エラー対策を万全に行ったとしても、いくつかのエラーは不可避です。以下の戦略は、これらのエラーへの対処方法に焦点を当てています。

エラーメッセージを注意深く読む

前述のように、Pythonは通常、エラーの性質と発生場所に関する情報を含んだエラーメッセージを表示します。

これらのエラーメッセージを注意深く読むことにより、問題の原因や解決方法についての貴重な手がかりが得られます。

print文を戦略的に使用する

 print() 文の使用は、実行フローをトレースしたり、特定のポイントでの変数値を検証したりする必要がある小規模なプロジェクトや、単純な問題の迅速かつ効果的なデバッグ方法です。問題の原因がよく理解できている場合や、迅速な開発に特に役立ちます。

printデバッグの使用は簡単で、実装も速やかに行えるため、単純なバグなどの解決に最適です。ただし、このデバッグ方法は一時的な使用のみを前提としており、エンドユーザーに表示されたデータを出力すると深刻なデータ漏洩やパフォーマンス上の問題につながる可能性があるため、プロダクションコードでは使用しないようにしましょう。

問題がより複雑である場合や、コードベースが大規模である場合、またプログラムの状態をより詳細に検証する必要がある場合(複数の関数呼び出しまたは繰り返しにおける可変状態など)には、デバッガーの使用がより適切となります。デバッガーを使用すると、ブレークポイントを設定したり、コードを1行ずつステップ実行したり、またいつでもアプリケーションの状態を検証したりすることもできるため、より包括的で制御されたデバッグ環境を実現できます。

オンラインリソースとコミュニティを活用する

解決が困難なエラーにより行き詰まってしまった場合は、迷わず助けを求めましょう。問題に対する答えや解決策を見つけることができるオンラインリソース(Python Docs や Real Python)やコミュニティ(r/Python や r/LearnPython サブレディット、 Stack Overflow、 Python Forumなど)は多数あります。

まとめ

今回の記事では、Pythonにおける構文エラーの世界に触れました。そして、各種構文エラーの発生しやすい場所や、特定および解決方法などについて学びました。

また、構文エラーの防止や解決に役立つ、事前戦略および事後対応についても学びました。

Bright Data は、世界をリードするWebスクレイピングツールのプロバイダーです。Webスクレイピングの効率と生産性の向上に貢献するソリューションとして、信頼できるプロキシや自動データ収集機能、 すぐに使えるデータセット、そして Webスクレイピングタスクの自動化機能を提供しています。

今すぐ登録し、スクレイピングのニーズに合った商品を見つけ出して、無料トライアルを始めましょう!

クレジットカードは必要ありません